@flanksource/clicky-ui 0.3.1 → 0.3.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 (382) hide show
  1. package/dist/comments/CommentAuthor.cjs +58 -0
  2. package/dist/comments/CommentAuthor.cjs.map +1 -0
  3. package/dist/comments/CommentAuthor.d.ts +17 -0
  4. package/dist/comments/CommentAuthor.d.ts.map +1 -0
  5. package/dist/comments/CommentAuthor.js +58 -0
  6. package/dist/comments/CommentAuthor.js.map +1 -0
  7. package/dist/comments/CommentCard.cjs +343 -0
  8. package/dist/comments/CommentCard.cjs.map +1 -0
  9. package/dist/comments/CommentCard.d.ts +27 -0
  10. package/dist/comments/CommentCard.d.ts.map +1 -0
  11. package/dist/comments/CommentCard.js +343 -0
  12. package/dist/comments/CommentCard.js.map +1 -0
  13. package/dist/comments/CommentComposer.cjs +207 -0
  14. package/dist/comments/CommentComposer.cjs.map +1 -0
  15. package/dist/comments/CommentComposer.d.ts +23 -0
  16. package/dist/comments/CommentComposer.d.ts.map +1 -0
  17. package/dist/comments/CommentComposer.js +207 -0
  18. package/dist/comments/CommentComposer.js.map +1 -0
  19. package/dist/comments/CommentFilterBar.cjs +145 -0
  20. package/dist/comments/CommentFilterBar.cjs.map +1 -0
  21. package/dist/comments/CommentFilterBar.d.ts +15 -0
  22. package/dist/comments/CommentFilterBar.d.ts.map +1 -0
  23. package/dist/comments/CommentFilterBar.js +145 -0
  24. package/dist/comments/CommentFilterBar.js.map +1 -0
  25. package/dist/comments/CommentMarkdown.cjs +156 -0
  26. package/dist/comments/CommentMarkdown.cjs.map +1 -0
  27. package/dist/comments/CommentMarkdown.d.ts +13 -0
  28. package/dist/comments/CommentMarkdown.d.ts.map +1 -0
  29. package/dist/comments/CommentMarkdown.js +156 -0
  30. package/dist/comments/CommentMarkdown.js.map +1 -0
  31. package/dist/comments/CommentProgress.cjs +86 -0
  32. package/dist/comments/CommentProgress.cjs.map +1 -0
  33. package/dist/comments/CommentProgress.d.ts +16 -0
  34. package/dist/comments/CommentProgress.d.ts.map +1 -0
  35. package/dist/comments/CommentProgress.js +86 -0
  36. package/dist/comments/CommentProgress.js.map +1 -0
  37. package/dist/comments/CommentProvider.cjs +99 -0
  38. package/dist/comments/CommentProvider.cjs.map +1 -0
  39. package/dist/comments/CommentProvider.d.ts +19 -0
  40. package/dist/comments/CommentProvider.d.ts.map +1 -0
  41. package/dist/comments/CommentProvider.js +99 -0
  42. package/dist/comments/CommentProvider.js.map +1 -0
  43. package/dist/comments/CommentSidePanel.cjs +219 -0
  44. package/dist/comments/CommentSidePanel.cjs.map +1 -0
  45. package/dist/comments/CommentSidePanel.d.ts +16 -0
  46. package/dist/comments/CommentSidePanel.d.ts.map +1 -0
  47. package/dist/comments/CommentSidePanel.js +219 -0
  48. package/dist/comments/CommentSidePanel.js.map +1 -0
  49. package/dist/comments/CommentThread.cjs +57 -0
  50. package/dist/comments/CommentThread.cjs.map +1 -0
  51. package/dist/comments/CommentThread.d.ts +24 -0
  52. package/dist/comments/CommentThread.d.ts.map +1 -0
  53. package/dist/comments/CommentThread.js +57 -0
  54. package/dist/comments/CommentThread.js.map +1 -0
  55. package/dist/comments/CommentThreadList.cjs +124 -0
  56. package/dist/comments/CommentThreadList.cjs.map +1 -0
  57. package/dist/comments/CommentThreadList.d.ts +25 -0
  58. package/dist/comments/CommentThreadList.d.ts.map +1 -0
  59. package/dist/comments/CommentThreadList.js +124 -0
  60. package/dist/comments/CommentThreadList.js.map +1 -0
  61. package/dist/comments/GroupedComments.cjs +74 -0
  62. package/dist/comments/GroupedComments.cjs.map +1 -0
  63. package/dist/comments/GroupedComments.d.ts +18 -0
  64. package/dist/comments/GroupedComments.d.ts.map +1 -0
  65. package/dist/comments/GroupedComments.js +74 -0
  66. package/dist/comments/GroupedComments.js.map +1 -0
  67. package/dist/comments/MentionTextarea.cjs +253 -0
  68. package/dist/comments/MentionTextarea.cjs.map +1 -0
  69. package/dist/comments/MentionTextarea.d.ts +28 -0
  70. package/dist/comments/MentionTextarea.d.ts.map +1 -0
  71. package/dist/comments/MentionTextarea.js +253 -0
  72. package/dist/comments/MentionTextarea.js.map +1 -0
  73. package/dist/comments/comment-context.cjs +33 -0
  74. package/dist/comments/comment-context.cjs.map +1 -0
  75. package/dist/comments/comment-context.d.ts +32 -0
  76. package/dist/comments/comment-context.d.ts.map +1 -0
  77. package/dist/comments/comment-context.js +33 -0
  78. package/dist/comments/comment-context.js.map +1 -0
  79. package/dist/comments/comment-fixtures.d.ts +11 -0
  80. package/dist/comments/comment-fixtures.d.ts.map +1 -0
  81. package/dist/comments/comment-types.cjs +19 -0
  82. package/dist/comments/comment-types.cjs.map +1 -0
  83. package/dist/comments/comment-types.d.ts +170 -0
  84. package/dist/comments/comment-types.d.ts.map +1 -0
  85. package/dist/comments/comment-types.js +19 -0
  86. package/dist/comments/comment-types.js.map +1 -0
  87. package/dist/comments/comment-utils.cjs +216 -0
  88. package/dist/comments/comment-utils.cjs.map +1 -0
  89. package/dist/comments/comment-utils.d.ts +59 -0
  90. package/dist/comments/comment-utils.d.ts.map +1 -0
  91. package/dist/comments/comment-utils.js +216 -0
  92. package/dist/comments/comment-utils.js.map +1 -0
  93. package/dist/comments.cjs +57 -0
  94. package/dist/comments.cjs.map +1 -0
  95. package/dist/comments.d.ts +16 -0
  96. package/dist/comments.d.ts.map +1 -0
  97. package/dist/comments.js +57 -0
  98. package/dist/comments.js.map +1 -0
  99. package/dist/components/FilterBar.cjs +13 -3
  100. package/dist/components/FilterBar.cjs.map +1 -1
  101. package/dist/components/FilterBar.js +13 -3
  102. package/dist/components/FilterBar.js.map +1 -1
  103. package/dist/components/JsonSchemaForm.cjs +20 -6
  104. package/dist/components/JsonSchemaForm.cjs.map +1 -1
  105. package/dist/components/JsonSchemaForm.d.ts +1 -1
  106. package/dist/components/JsonSchemaForm.d.ts.map +1 -1
  107. package/dist/components/JsonSchemaForm.js +22 -8
  108. package/dist/components/JsonSchemaForm.js.map +1 -1
  109. package/dist/components/NamespacePicker.cjs +52 -0
  110. package/dist/components/NamespacePicker.cjs.map +1 -0
  111. package/dist/components/NamespacePicker.d.ts +17 -0
  112. package/dist/components/NamespacePicker.d.ts.map +1 -0
  113. package/dist/components/NamespacePicker.js +52 -0
  114. package/dist/components/NamespacePicker.js.map +1 -0
  115. package/dist/components/form-lookup-context.cjs +36 -0
  116. package/dist/components/form-lookup-context.cjs.map +1 -0
  117. package/dist/components/form-lookup-context.d.ts +9 -0
  118. package/dist/components/form-lookup-context.d.ts.map +1 -0
  119. package/dist/components/form-lookup-context.js +36 -0
  120. package/dist/components/form-lookup-context.js.map +1 -0
  121. package/dist/components/json-schema-form-discriminator.cjs +67 -0
  122. package/dist/components/json-schema-form-discriminator.cjs.map +1 -0
  123. package/dist/components/json-schema-form-discriminator.d.ts +10 -0
  124. package/dist/components/json-schema-form-discriminator.d.ts.map +1 -0
  125. package/dist/components/json-schema-form-discriminator.js +67 -0
  126. package/dist/components/json-schema-form-discriminator.js.map +1 -0
  127. package/dist/components/json-schema-form-fields.cjs +66 -1
  128. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  129. package/dist/components/json-schema-form-fields.d.ts +7 -0
  130. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  131. package/dist/components/json-schema-form-fields.js +66 -1
  132. package/dist/components/json-schema-form-fields.js.map +1 -1
  133. package/dist/components/json-schema-form-grid.cjs +92 -0
  134. package/dist/components/json-schema-form-grid.cjs.map +1 -0
  135. package/dist/components/json-schema-form-grid.d.ts +9 -0
  136. package/dist/components/json-schema-form-grid.d.ts.map +1 -0
  137. package/dist/components/json-schema-form-grid.js +92 -0
  138. package/dist/components/json-schema-form-grid.js.map +1 -0
  139. package/dist/components/json-schema-form-render.cjs +20 -3
  140. package/dist/components/json-schema-form-render.cjs.map +1 -1
  141. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  142. package/dist/components/json-schema-form-render.js +22 -5
  143. package/dist/components/json-schema-form-render.js.map +1 -1
  144. package/dist/components/json-schema-form-resolve.cjs +24 -2
  145. package/dist/components/json-schema-form-resolve.cjs.map +1 -1
  146. package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
  147. package/dist/components/json-schema-form-resolve.js +24 -2
  148. package/dist/components/json-schema-form-resolve.js.map +1 -1
  149. package/dist/components/json-schema-form-types.d.ts +37 -2
  150. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  151. package/dist/components/json-schema-form-utils.cjs +8 -0
  152. package/dist/components/json-schema-form-utils.cjs.map +1 -1
  153. package/dist/components/json-schema-form-utils.d.ts +1 -0
  154. package/dist/components/json-schema-form-utils.d.ts.map +1 -1
  155. package/dist/components/json-schema-form-utils.js +8 -0
  156. package/dist/components/json-schema-form-utils.js.map +1 -1
  157. package/dist/components/workload-picker-utils.cjs.map +1 -1
  158. package/dist/components/workload-picker-utils.d.ts +11 -1
  159. package/dist/components/workload-picker-utils.d.ts.map +1 -1
  160. package/dist/components/workload-picker-utils.js.map +1 -1
  161. package/dist/components.cjs +6 -0
  162. package/dist/components.cjs.map +1 -1
  163. package/dist/components.d.ts +4 -2
  164. package/dist/components.d.ts.map +1 -1
  165. package/dist/components.js +6 -0
  166. package/dist/components.js.map +1 -1
  167. package/dist/data/Clicky.cjs +225 -60
  168. package/dist/data/Clicky.cjs.map +1 -1
  169. package/dist/data/Clicky.d.ts +7 -1
  170. package/dist/data/Clicky.d.ts.map +1 -1
  171. package/dist/data/Clicky.fixtures.d.ts +3 -1
  172. package/dist/data/Clicky.fixtures.d.ts.map +1 -1
  173. package/dist/data/Clicky.js +226 -61
  174. package/dist/data/Clicky.js.map +1 -1
  175. package/dist/data/ExecutionTree.cjs +68 -0
  176. package/dist/data/ExecutionTree.cjs.map +1 -0
  177. package/dist/data/ExecutionTree.d.ts +40 -0
  178. package/dist/data/ExecutionTree.d.ts.map +1 -0
  179. package/dist/data/ExecutionTree.js +68 -0
  180. package/dist/data/ExecutionTree.js.map +1 -0
  181. package/dist/data/GaugeHoverCard.cjs +35 -0
  182. package/dist/data/GaugeHoverCard.cjs.map +1 -0
  183. package/dist/data/GaugeHoverCard.d.ts +25 -0
  184. package/dist/data/GaugeHoverCard.d.ts.map +1 -0
  185. package/dist/data/GaugeHoverCard.js +35 -0
  186. package/dist/data/GaugeHoverCard.js.map +1 -0
  187. package/dist/data/MarkdownEditor.cjs +616 -0
  188. package/dist/data/MarkdownEditor.cjs.map +1 -0
  189. package/dist/data/MarkdownEditor.d.ts +61 -0
  190. package/dist/data/MarkdownEditor.d.ts.map +1 -0
  191. package/dist/data/MarkdownEditor.js +616 -0
  192. package/dist/data/MarkdownEditor.js.map +1 -0
  193. package/dist/data/MarkdownEditor.model.cjs +27 -0
  194. package/dist/data/MarkdownEditor.model.cjs.map +1 -0
  195. package/dist/data/MarkdownEditor.model.d.ts +38 -0
  196. package/dist/data/MarkdownEditor.model.d.ts.map +1 -0
  197. package/dist/data/MarkdownEditor.model.js +27 -0
  198. package/dist/data/MarkdownEditor.model.js.map +1 -0
  199. package/dist/data/ObjectGraph.cjs +44 -0
  200. package/dist/data/ObjectGraph.cjs.map +1 -0
  201. package/dist/data/ObjectGraph.d.ts +39 -0
  202. package/dist/data/ObjectGraph.d.ts.map +1 -0
  203. package/dist/data/ObjectGraph.js +44 -0
  204. package/dist/data/ObjectGraph.js.map +1 -0
  205. package/dist/data/SchemaViewer.cjs +152 -0
  206. package/dist/data/SchemaViewer.cjs.map +1 -0
  207. package/dist/data/SchemaViewer.d.ts +27 -0
  208. package/dist/data/SchemaViewer.d.ts.map +1 -0
  209. package/dist/data/SchemaViewer.js +152 -0
  210. package/dist/data/SchemaViewer.js.map +1 -0
  211. package/dist/data/TimeseriesCoreBars.cjs +51 -12
  212. package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
  213. package/dist/data/TimeseriesCoreBars.d.ts +32 -5
  214. package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
  215. package/dist/data/TimeseriesCoreBars.js +51 -12
  216. package/dist/data/TimeseriesCoreBars.js.map +1 -1
  217. package/dist/data/TimeseriesCoreBars.model.cjs +5 -5
  218. package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -1
  219. package/dist/data/TimeseriesCoreBars.model.d.ts +4 -4
  220. package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -1
  221. package/dist/data/TimeseriesCoreBars.model.js +5 -5
  222. package/dist/data/TimeseriesCoreBars.model.js.map +1 -1
  223. package/dist/data/TimeseriesGauge.cjs +103 -65
  224. package/dist/data/TimeseriesGauge.cjs.map +1 -1
  225. package/dist/data/TimeseriesGauge.d.ts +10 -1
  226. package/dist/data/TimeseriesGauge.d.ts.map +1 -1
  227. package/dist/data/TimeseriesGauge.js +104 -66
  228. package/dist/data/TimeseriesGauge.js.map +1 -1
  229. package/dist/data/WorkloadCard.cjs +4 -4
  230. package/dist/data/WorkloadCard.cjs.map +1 -1
  231. package/dist/data/WorkloadCard.d.ts +3 -2
  232. package/dist/data/WorkloadCard.d.ts.map +1 -1
  233. package/dist/data/WorkloadCard.js +4 -4
  234. package/dist/data/WorkloadCard.js.map +1 -1
  235. package/dist/data/ai/ChatWindow.cjs +11 -19
  236. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  237. package/dist/data/ai/ChatWindow.d.ts +1 -7
  238. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  239. package/dist/data/ai/ChatWindow.js +11 -19
  240. package/dist/data/ai/ChatWindow.js.map +1 -1
  241. package/dist/data/ai/ChatWindowRequestBody.cjs +20 -0
  242. package/dist/data/ai/ChatWindowRequestBody.cjs.map +1 -0
  243. package/dist/data/ai/ChatWindowRequestBody.d.ts +9 -0
  244. package/dist/data/ai/ChatWindowRequestBody.d.ts.map +1 -0
  245. package/dist/data/ai/ChatWindowRequestBody.js +20 -0
  246. package/dist/data/ai/ChatWindowRequestBody.js.map +1 -0
  247. package/dist/data/chat/Chat.cjs +12 -0
  248. package/dist/data/chat/Chat.cjs.map +1 -1
  249. package/dist/data/chat/Chat.d.ts +8 -1
  250. package/dist/data/chat/Chat.d.ts.map +1 -1
  251. package/dist/data/chat/Chat.js +12 -0
  252. package/dist/data/chat/Chat.js.map +1 -1
  253. package/dist/data/gauge-stats.cjs +19 -0
  254. package/dist/data/gauge-stats.cjs.map +1 -0
  255. package/dist/data/gauge-stats.d.ts +15 -0
  256. package/dist/data/gauge-stats.d.ts.map +1 -0
  257. package/dist/data/gauge-stats.js +19 -0
  258. package/dist/data/gauge-stats.js.map +1 -0
  259. package/dist/data/schema-viewer-model.cjs +436 -0
  260. package/dist/data/schema-viewer-model.cjs.map +1 -0
  261. package/dist/data/schema-viewer-model.d.ts +64 -0
  262. package/dist/data/schema-viewer-model.d.ts.map +1 -0
  263. package/dist/data/schema-viewer-model.js +436 -0
  264. package/dist/data/schema-viewer-model.js.map +1 -0
  265. package/dist/data/version-info.cjs +2 -2
  266. package/dist/data/version-info.js +2 -2
  267. package/dist/data.cjs +23 -0
  268. package/dist/data.cjs.map +1 -1
  269. package/dist/data.d.ts +11 -3
  270. package/dist/data.d.ts.map +1 -1
  271. package/dist/data.js +23 -0
  272. package/dist/data.js.map +1 -1
  273. package/dist/index.cjs +87 -2
  274. package/dist/index.cjs.map +1 -1
  275. package/dist/index.d.ts +1 -0
  276. package/dist/index.d.ts.map +1 -1
  277. package/dist/index.js +87 -2
  278. package/dist/index.js.map +1 -1
  279. package/dist/rpc/EntityExplorerApp.cjs +102 -143
  280. package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
  281. package/dist/rpc/EntityExplorerApp.d.ts +34 -1
  282. package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
  283. package/dist/rpc/EntityExplorerApp.js +105 -146
  284. package/dist/rpc/EntityExplorerApp.js.map +1 -1
  285. package/dist/rpc/OperationActionBar.cjs +135 -0
  286. package/dist/rpc/OperationActionBar.cjs.map +1 -0
  287. package/dist/rpc/OperationActionBar.d.ts +20 -0
  288. package/dist/rpc/OperationActionBar.d.ts.map +1 -0
  289. package/dist/rpc/OperationActionBar.js +135 -0
  290. package/dist/rpc/OperationActionBar.js.map +1 -0
  291. package/dist/rpc/OperationCatalog.cjs +79 -116
  292. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  293. package/dist/rpc/OperationCatalog.d.ts +8 -1
  294. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  295. package/dist/rpc/OperationCatalog.js +80 -117
  296. package/dist/rpc/OperationCatalog.js.map +1 -1
  297. package/dist/rpc/OperationCommandPage.cjs +134 -223
  298. package/dist/rpc/OperationCommandPage.cjs.map +1 -1
  299. package/dist/rpc/OperationCommandPage.d.ts +1 -1
  300. package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
  301. package/dist/rpc/OperationCommandPage.js +135 -224
  302. package/dist/rpc/OperationCommandPage.js.map +1 -1
  303. package/dist/rpc/OperationEntityPage.cjs +49 -100
  304. package/dist/rpc/OperationEntityPage.cjs.map +1 -1
  305. package/dist/rpc/OperationEntityPage.d.ts +6 -1
  306. package/dist/rpc/OperationEntityPage.d.ts.map +1 -1
  307. package/dist/rpc/OperationEntityPage.js +50 -101
  308. package/dist/rpc/OperationEntityPage.js.map +1 -1
  309. package/dist/rpc/OperationResultView.cjs +43 -0
  310. package/dist/rpc/OperationResultView.cjs.map +1 -0
  311. package/dist/rpc/OperationResultView.d.ts +30 -0
  312. package/dist/rpc/OperationResultView.d.ts.map +1 -0
  313. package/dist/rpc/OperationResultView.js +43 -0
  314. package/dist/rpc/OperationResultView.js.map +1 -0
  315. package/dist/rpc/SchemaActionForm.cjs +102 -0
  316. package/dist/rpc/SchemaActionForm.cjs.map +1 -0
  317. package/dist/rpc/SchemaActionForm.d.ts +23 -0
  318. package/dist/rpc/SchemaActionForm.d.ts.map +1 -0
  319. package/dist/rpc/SchemaActionForm.js +102 -0
  320. package/dist/rpc/SchemaActionForm.js.map +1 -0
  321. package/dist/rpc/accept-options.cjs.map +1 -1
  322. package/dist/rpc/accept-options.d.ts +0 -1
  323. package/dist/rpc/accept-options.d.ts.map +1 -1
  324. package/dist/rpc/accept-options.js.map +1 -1
  325. package/dist/rpc/apiClient.cjs +34 -2
  326. package/dist/rpc/apiClient.cjs.map +1 -1
  327. package/dist/rpc/apiClient.d.ts +4 -1
  328. package/dist/rpc/apiClient.d.ts.map +1 -1
  329. package/dist/rpc/apiClient.js +34 -2
  330. package/dist/rpc/apiClient.js.map +1 -1
  331. package/dist/rpc/clickyMetadata.cjs +4 -4
  332. package/dist/rpc/clickyMetadata.cjs.map +1 -1
  333. package/dist/rpc/clickyMetadata.d.ts +0 -1
  334. package/dist/rpc/clickyMetadata.d.ts.map +1 -1
  335. package/dist/rpc/clickyMetadata.js +4 -4
  336. package/dist/rpc/clickyMetadata.js.map +1 -1
  337. package/dist/rpc/formMetadata.cjs +1 -0
  338. package/dist/rpc/formMetadata.cjs.map +1 -1
  339. package/dist/rpc/formMetadata.d.ts +6 -1
  340. package/dist/rpc/formMetadata.d.ts.map +1 -1
  341. package/dist/rpc/formMetadata.js +1 -0
  342. package/dist/rpc/formMetadata.js.map +1 -1
  343. package/dist/rpc/rowNavigation.cjs +86 -0
  344. package/dist/rpc/rowNavigation.cjs.map +1 -0
  345. package/dist/rpc/rowNavigation.d.ts +14 -0
  346. package/dist/rpc/rowNavigation.d.ts.map +1 -0
  347. package/dist/rpc/rowNavigation.js +86 -0
  348. package/dist/rpc/rowNavigation.js.map +1 -0
  349. package/dist/rpc/schemaActionPath.cjs +22 -0
  350. package/dist/rpc/schemaActionPath.cjs.map +1 -0
  351. package/dist/rpc/schemaActionPath.d.ts +4 -0
  352. package/dist/rpc/schemaActionPath.d.ts.map +1 -0
  353. package/dist/rpc/schemaActionPath.js +22 -0
  354. package/dist/rpc/schemaActionPath.js.map +1 -0
  355. package/dist/rpc/surfaceIconMap.cjs +35 -0
  356. package/dist/rpc/surfaceIconMap.cjs.map +1 -0
  357. package/dist/rpc/surfaceIconMap.d.ts +3 -0
  358. package/dist/rpc/surfaceIconMap.d.ts.map +1 -0
  359. package/dist/rpc/surfaceIconMap.js +35 -0
  360. package/dist/rpc/surfaceIconMap.js.map +1 -0
  361. package/dist/rpc/types.cjs.map +1 -1
  362. package/dist/rpc/types.d.ts +2 -0
  363. package/dist/rpc/types.d.ts.map +1 -1
  364. package/dist/rpc/types.js.map +1 -1
  365. package/dist/rpc/useOperations.cjs.map +1 -1
  366. package/dist/rpc/useOperations.d.ts +4 -1
  367. package/dist/rpc/useOperations.d.ts.map +1 -1
  368. package/dist/rpc/useOperations.js.map +1 -1
  369. package/dist/rpc.cjs +4 -2
  370. package/dist/rpc.cjs.map +1 -1
  371. package/dist/rpc.d.ts +7 -6
  372. package/dist/rpc.d.ts.map +1 -1
  373. package/dist/rpc.js +4 -2
  374. package/dist/rpc.js.map +1 -1
  375. package/dist/styles.css +1 -1
  376. package/package.json +6 -1
  377. package/dist/rpc/AcceptPicker.cjs +0 -137
  378. package/dist/rpc/AcceptPicker.cjs.map +0 -1
  379. package/dist/rpc/AcceptPicker.d.ts +0 -12
  380. package/dist/rpc/AcceptPicker.d.ts.map +0 -1
  381. package/dist/rpc/AcceptPicker.js +0 -137
  382. package/dist/rpc/AcceptPicker.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TimeseriesCoreBars.js","sources":["../../src/data/TimeseriesCoreBars.tsx"],"sourcesContent":["import { useQueries } from \"@tanstack/react-query\";\nimport { useMemo } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport type { GaugeSeries } from \"./TimeseriesGauge\";\nimport type { TimeseriesResponse } from \"./TimeseriesPanel\";\nimport { deriveCoreBars } from \"./TimeseriesCoreBars.model\";\n\nexport type TimeseriesCoreBarsVariant = \"default\" | \"cell\";\nexport type TimeseriesCoreBarsOrientation = \"horizontal\" | \"vertical\";\n\nexport interface TimeseriesCoreBarsProps {\n /** Common prefix; the value/max requests are `baseUrl + id`. */\n baseUrl?: string;\n /** The metric whose latest value (CPU millicores) fills the bars. */\n value: GaugeSeries;\n /**\n * The CPU capacity. Either a `.limit`-style metric series (its latest value in\n * millicores) or a fixed number of millicores. Determines the number of bars\n * (one per core). When omitted or 0, the bar count falls back to the ceiling of\n * the usage in cores so an unbounded reading still renders.\n */\n max?: GaugeSeries | number;\n title: string;\n /** Iconify name or static icon component shown beside the label. */\n icon?: string | StaticIconComponent;\n /** Look-back window passed as ?since=; defaults to \"1h\". */\n range?: string;\n /** Poll interval in ms; defaults to 5000. Pass 0 to disable polling. */\n refreshMs?: number;\n /**\n * Utilisation thresholds (percent of capacity) at which the fill turns amber\n * then red. Defaults to [75, 90].\n */\n thresholds?: [warning: number, danger: number];\n /** Visual density/layout. `cell` is a compact inline form for table/grid cells. */\n variant?: TimeseriesCoreBarsVariant;\n /** Show the title text. Icons and values remain visible unless separately hidden. */\n showLabel?: boolean;\n /** Show the value/capacity caption. Icons and bars remain visible when false. */\n showValue?: boolean;\n /** Bar direction. Vertical bars fill bottom-up; horizontal bars fill left-to-right. */\n orientation?: TimeseriesCoreBarsOrientation;\n /** Override the default fetch (e.g. to route through an app's API client). */\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nconst defaultFetcher = async (url: string): Promise<TimeseriesResponse> => {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);\n return res.json();\n};\n\nfunction latestValue(resp: TimeseriesResponse | undefined): number | undefined {\n const points = resp?.points;\n if (!points || points.length === 0) return undefined;\n return points[points.length - 1]?.value;\n}\n\nfunction toneClass(pct: number, [warn, danger]: [number, number]): string {\n if (pct >= danger) return \"bg-red-500\";\n if (pct >= warn) return \"bg-amber-500\";\n return \"bg-emerald-500\";\n}\n\nfunction CoreBarsIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return (\n <Icon\n name={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n }\n return (\n <Icon\n icon={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n}\n\nfunction formatCores(cores: number): string {\n return Number.isInteger(cores) ? String(cores) : cores.toFixed(1);\n}\n\n/**\n * TimeseriesCoreBars renders CPU utilisation as a row of vertical bars — one bar\n * per core (the ceiling of the CPU limit) — filled left to right by the latest\n * usage. The bar that straddles the usage boundary is partially filled (\"blocked\n * out\") to show the fractional core in use, and the trailing bars stay empty to\n * show headroom. Both usage and limit are read live from the timeseries store,\n * mirroring TimeseriesGauge's data plumbing; the bar colour crosses warning and\n * danger thresholds. A \"<used> / <cores>\" caption sits below with the icon+title.\n */\nexport function TimeseriesCoreBars({\n baseUrl = \"\",\n value,\n max,\n title,\n icon,\n range = \"1h\",\n refreshMs = 5000,\n thresholds = [75, 90],\n variant = \"default\",\n showLabel = true,\n showValue = true,\n orientation,\n fetcher = defaultFetcher,\n className,\n}: TimeseriesCoreBarsProps) {\n const maxIsSeries = typeof max === \"object\";\n const maxSeries = maxIsSeries ? max : undefined;\n const ids = useMemo(() => {\n const list = [value.id];\n if (maxSeries) list.push(maxSeries.id);\n return list;\n }, [value.id, maxSeries]);\n\n const results = useQueries({\n queries: ids.map((id) => {\n const u = new URL(baseUrl + id, window.location.origin);\n if (range) u.searchParams.set(\"since\", range);\n const requestUrl = u.pathname + u.search;\n return {\n queryKey: [\"timeseries\", requestUrl],\n queryFn: () => fetcher(requestUrl),\n refetchInterval: refreshMs > 0 ? refreshMs : false,\n staleTime: 0,\n retry: 0,\n };\n }),\n });\n\n const rawValue = latestValue(results[0]?.data);\n const usage =\n rawValue === undefined\n ? undefined\n : value.transform\n ? value.transform(rawValue)\n : rawValue;\n\n let limit: number | undefined;\n if (typeof max === \"number\") {\n limit = max;\n } else if (maxSeries) {\n const rawMax = latestValue(results[1]?.data);\n limit =\n rawMax === undefined\n ? undefined\n : maxSeries.transform\n ? maxSeries.transform(rawMax)\n : rawMax;\n }\n\n const model = deriveCoreBars(usage, limit);\n const tone = toneClass(model.pct, thresholds);\n const caption = model.hasUsage\n ? `${formatCores(model.usageCores)} / ${model.limitCores !== undefined ? formatCores(model.limitCores) : \"?\"} cores`\n : \"—\";\n const compactCaption = model.hasUsage\n ? `${formatCores(model.usageCores)}/${model.limitCores !== undefined ? formatCores(model.limitCores) : \"?\"} cores`\n : \"—\";\n const titleText = `${title}: ${compactCaption}`;\n const isCell = variant === \"cell\";\n const resolvedOrientation = orientation ?? \"vertical\";\n const isDense = model.coreCount > 4;\n const valueText = isCell ? compactCaption : caption;\n const hiddenAccessibleText = !showLabel || !showValue ? titleText : undefined;\n const bars = (\n <span\n className={cn(\n \"flex shrink-0\",\n resolvedOrientation === \"vertical\"\n ? cn(\"items-end\", isCell ? \"h-4 gap-px\" : \"h-10 gap-0.5\")\n : cn(\n \"flex-col justify-center\",\n isCell ? \"h-4 w-10 gap-px\" : \"h-10 w-16 gap-0.5\",\n ),\n )}\n aria-hidden={isCell ? \"true\" : undefined}\n data-orientation={resolvedOrientation}\n data-core-count={model.coreCount}\n data-core-density={isDense ? \"compact\" : \"default\"}\n >\n {model.bars.map((bar, i) => {\n const corePct = Math.round(bar.fill * 100);\n return (\n <span\n key={i}\n className={cn(\n \"relative overflow-hidden bg-muted\",\n resolvedOrientation === \"vertical\"\n ? cn(\n \"h-full\",\n isCell\n ? isDense\n ? \"w-[3px] rounded-[2px]\"\n : \"w-1.5 rounded-[2px]\"\n : isDense\n ? \"w-1 rounded-sm\"\n : \"w-2 rounded-sm\",\n )\n : cn(\"min-h-px w-full flex-1 rounded-[2px]\"),\n )}\n title={`core ${i + 1}: ${corePct}%`}\n aria-label={!isCell ? `core ${i + 1}: ${corePct}%` : undefined}\n data-fill={bar.fill}\n >\n <span\n className={cn(\n \"absolute bottom-0 left-0 transition-all duration-300\",\n tone,\n )}\n style={\n resolvedOrientation === \"vertical\"\n ? { height: `${corePct}%`, right: 0 }\n : { width: `${corePct}%`, top: 0 }\n }\n />\n </span>\n );\n })}\n </span>\n );\n const valueNode = showValue ? (\n <span\n className={cn(\n \"shrink-0 font-semibold tabular-nums text-foreground\",\n isCell ? null : \"text-xs\",\n )}\n >\n {valueText}\n </span>\n ) : null;\n const label =\n icon || showLabel ? (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1 text-xs text-muted-foreground\",\n )}\n >\n {icon ? <CoreBarsIcon icon={icon} /> : null}\n {showLabel ? <span className=\"min-w-0 truncate\">{title}</span> : null}\n </span>\n ) : null;\n\n if (isCell) {\n return (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs\",\n className,\n )}\n title={titleText}\n aria-label={hiddenAccessibleText}\n >\n {label}\n {bars}\n {valueNode}\n </span>\n );\n }\n\n return (\n <div\n className={cn(\"flex flex-col items-center gap-1\", className)}\n title={hiddenAccessibleText}\n aria-label={hiddenAccessibleText}\n >\n {bars}\n {valueNode}\n {label}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;AAgDA,MAAM,iBAAiB,OAAO,QAA6C;AACzE,QAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,2BAA2B,IAAI,MAAM,EAAE;AACpE,SAAO,IAAI,KAAA;AACb;AAEA,SAAS,YAAY,MAA0D;;AAC7E,QAAM,SAAS,6BAAM;AACrB,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;AAC3C,UAAO,YAAO,OAAO,SAAS,CAAC,MAAxB,mBAA2B;AACpC;AAEA,SAAS,UAAU,KAAa,CAAC,MAAM,MAAM,GAA6B;AACxE,MAAI,OAAO,OAAQ,QAAO;AAC1B,MAAI,OAAO,KAAM,QAAO;AACxB,SAAO;AACT;AAEA,SAAS,aAAa,EAAE,QAAgD;AACtE,MAAI,OAAO,SAAS,UAAU;AAC5B,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,WAAU;AAAA,MAAA;AAAA,IAAA;AAAA,EAGhB;AACA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAU;AAAA,IAAA;AAAA,EAAA;AAGhB;AAEA,SAAS,YAAY,OAAuB;AAC1C,SAAO,OAAO,UAAU,KAAK,IAAI,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC;AAClE;AAWO,SAAS,mBAAmB;AAAA,EACjC,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,aAAa,CAAC,IAAI,EAAE;AAAA,EACpB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ;AAAA,EACA,UAAU;AAAA,EACV;AACF,GAA4B;;AAC1B,QAAM,cAAc,OAAO,QAAQ;AACnC,QAAM,YAAY,cAAc,MAAM;AACtC,QAAM,MAAM,QAAQ,MAAM;AACxB,UAAM,OAAO,CAAC,MAAM,EAAE;AACtB,QAAI,UAAW,MAAK,KAAK,UAAU,EAAE;AACrC,WAAO;AAAA,EACT,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC;AAExB,QAAM,UAAU,WAAW;AAAA,IACzB,SAAS,IAAI,IAAI,CAAC,OAAO;AACvB,YAAM,IAAI,IAAI,IAAI,UAAU,IAAI,OAAO,SAAS,MAAM;AACtD,UAAI,MAAO,GAAE,aAAa,IAAI,SAAS,KAAK;AAC5C,YAAM,aAAa,EAAE,WAAW,EAAE;AAClC,aAAO;AAAA,QACL,UAAU,CAAC,cAAc,UAAU;AAAA,QACnC,SAAS,MAAM,QAAQ,UAAU;AAAA,QACjC,iBAAiB,YAAY,IAAI,YAAY;AAAA,QAC7C,WAAW;AAAA,QACX,OAAO;AAAA,MAAA;AAAA,IAEX,CAAC;AAAA,EAAA,CACF;AAED,QAAM,WAAW,aAAY,aAAQ,CAAC,MAAT,mBAAY,IAAI;AAC7C,QAAM,QACJ,aAAa,SACT,SACA,MAAM,YACJ,MAAM,UAAU,QAAQ,IACxB;AAER,MAAI;AACJ,MAAI,OAAO,QAAQ,UAAU;AAC3B,YAAQ;AAAA,EACV,WAAW,WAAW;AACpB,UAAM,SAAS,aAAY,aAAQ,CAAC,MAAT,mBAAY,IAAI;AAC3C,YACE,WAAW,SACP,SACA,UAAU,YACR,UAAU,UAAU,MAAM,IAC1B;AAAA,EACV;AAEA,QAAM,QAAQ,eAAe,OAAO,KAAK;AACzC,QAAM,OAAO,UAAU,MAAM,KAAK,UAAU;AAC5C,QAAM,UAAU,MAAM,WAClB,GAAG,YAAY,MAAM,UAAU,CAAC,MAAM,MAAM,eAAe,SAAY,YAAY,MAAM,UAAU,IAAI,GAAG,WAC1G;AACJ,QAAM,iBAAiB,MAAM,WACzB,GAAG,YAAY,MAAM,UAAU,CAAC,IAAI,MAAM,eAAe,SAAY,YAAY,MAAM,UAAU,IAAI,GAAG,WACxG;AACJ,QAAM,YAAY,GAAG,KAAK,KAAK,cAAc;AAC7C,QAAM,SAAS,YAAY;AAC3B,QAAM,sBAAsB,eAAe;AAC3C,QAAM,UAAU,MAAM,YAAY;AAClC,QAAM,YAAY,SAAS,iBAAiB;AAC5C,QAAM,uBAAuB,CAAC,aAAa,CAAC,YAAY,YAAY;AACpE,QAAM,OACJ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,wBAAwB,aACpB,GAAG,aAAa,SAAS,eAAe,cAAc,IACtD;AAAA,UACE;AAAA,UACA,SAAS,oBAAoB;AAAA,QAAA;AAAA,MAC/B;AAAA,MAEN,eAAa,SAAS,SAAS;AAAA,MAC/B,oBAAkB;AAAA,MAClB,mBAAiB,MAAM;AAAA,MACvB,qBAAmB,UAAU,YAAY;AAAA,MAExC,UAAA,MAAM,KAAK,IAAI,CAAC,KAAK,MAAM;AAC1B,cAAM,UAAU,KAAK,MAAM,IAAI,OAAO,GAAG;AACzC,eACE;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAW;AAAA,cACT;AAAA,cACA,wBAAwB,aACpB;AAAA,gBACE;AAAA,gBACA,SACI,UACE,0BACA,wBACF,UACE,mBACA;AAAA,cAAA,IAER,GAAG,sCAAsC;AAAA,YAAA;AAAA,YAE/C,OAAO,QAAQ,IAAI,CAAC,KAAK,OAAO;AAAA,YAChC,cAAY,CAAC,SAAS,QAAQ,IAAI,CAAC,KAAK,OAAO,MAAM;AAAA,YACrD,aAAW,IAAI;AAAA,YAEf,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA;AAAA,gBAAA;AAAA,gBAEF,OACE,wBAAwB,aACpB,EAAE,QAAQ,GAAG,OAAO,KAAK,OAAO,EAAA,IAChC,EAAE,OAAO,GAAG,OAAO,KAAK,KAAK,EAAA;AAAA,cAAE;AAAA,YAAA;AAAA,UAEvC;AAAA,UA9BK;AAAA,QAAA;AAAA,MAiCX,CAAC;AAAA,IAAA;AAAA,EAAA;AAGL,QAAM,YAAY,YAChB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,SAAS,OAAO;AAAA,MAAA;AAAA,MAGjB,UAAA;AAAA,IAAA;AAAA,EAAA,IAED;AACJ,QAAM,QACJ,QAAQ,YACN;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,MAAA;AAAA,MAGD,UAAA;AAAA,QAAA,OAAO,oBAAC,cAAA,EAAa,KAAA,CAAY,IAAK;AAAA,QACtC,YAAY,oBAAC,QAAA,EAAK,WAAU,oBAAoB,iBAAM,IAAU;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,IAEjE;AAEN,MAAI,QAAQ;AACV,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAEF,OAAO;AAAA,QACP,cAAY;AAAA,QAEX,UAAA;AAAA,UAAA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,GAAG,oCAAoC,SAAS;AAAA,MAC3D,OAAO;AAAA,MACP,cAAY;AAAA,MAEX,UAAA;AAAA,QAAA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;"}
1
+ {"version":3,"file":"TimeseriesCoreBars.js","sources":["../../src/data/TimeseriesCoreBars.tsx"],"sourcesContent":["import { useQueries } from \"@tanstack/react-query\";\nimport { useMemo } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport type { GaugeSeries } from \"./TimeseriesGauge\";\nimport type { TimeseriesResponse } from \"./TimeseriesPanel\";\nimport { deriveCoreBars } from \"./TimeseriesCoreBars.model\";\nimport { GaugeHoverCard, type GaugeHoverRow } from \"./GaugeHoverCard\";\nimport { seriesStats } from \"./gauge-stats\";\n\nexport type TimeseriesCoreBarsVariant = \"default\" | \"cell\";\nexport type TimeseriesCoreBarsOrientation = \"horizontal\" | \"vertical\";\n\n/**\n * Describes what one bar represents, letting the same component render CPU cores,\n * memory gigabytes, or any other quantised capacity. Defaults model CPU cores.\n */\nexport interface CoreBarsUnit {\n /** Raw value that fills one bar, in the domain of `value`/`max`. Default 1000 (millicores → 1 core). */\n perBar?: number;\n /** Caption/tooltip suffix naming the unit, plural. Default \"cores\". */\n label?: string;\n /** Per-bar hover tooltip noun, singular. Default \"core\". */\n barLabel?: string;\n /** Format a bar-unit count for the caption. Default: integers as-is, else 1 decimal. */\n format?: (units: number) => string;\n}\n\nexport interface TimeseriesCoreBarsProps {\n /** Common prefix; the value/max requests are `baseUrl + id`. */\n baseUrl?: string;\n /** The metric whose latest value (CPU millicores) fills the bars. */\n value: GaugeSeries;\n /**\n * The capacity. Either a `.limit`-style metric series (its latest value) or a\n * fixed number, in the same raw domain as `value`. Determines the number of\n * bars (one per `unit.perBar`). When omitted or 0, the bar count falls back to\n * the ceiling of the usage so an unbounded reading still renders.\n */\n max?: GaugeSeries | number;\n /** What one bar represents. Defaults to CPU cores (perBar 1000, label \"cores\"). */\n unit?: CoreBarsUnit;\n title: string;\n /** Iconify name or static icon component shown beside the label. */\n icon?: string | StaticIconComponent;\n /** Look-back window passed as ?since=; defaults to \"1h\". */\n range?: string;\n /** Poll interval in ms; defaults to 5000. Pass 0 to disable polling. */\n refreshMs?: number;\n /**\n * Utilisation thresholds (percent of capacity) at which the fill turns amber\n * then red. Defaults to [75, 90].\n */\n thresholds?: [warning: number, danger: number];\n /** Visual density/layout. `cell` is a compact inline form for table/grid cells. */\n variant?: TimeseriesCoreBarsVariant;\n /** Show the title text. Icons and values remain visible unless separately hidden. */\n showLabel?: boolean;\n /** Show the value/capacity caption. Icons and bars remain visible when false. */\n showValue?: boolean;\n /**\n * Include the capacity in the caption (\"2.3 / 4 cores\"). Defaults to false — the\n * caption shows only the current value (\"2.3 cores\") since the bars already\n * convey capacity. Set true to append the \"/ <capacity>\".\n */\n showCapacity?: boolean;\n /** Bar direction. Vertical bars fill bottom-up; horizontal bars fill left-to-right. */\n orientation?: TimeseriesCoreBarsOrientation;\n /**\n * Wrap the bars in a hover card summarising the metric (label + current / min /\n * max / avg / capacity over the window). Defaults to true.\n */\n hoverCard?: boolean;\n /** Override the default fetch (e.g. to route through an app's API client). */\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nconst defaultFetcher = async (url: string): Promise<TimeseriesResponse> => {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);\n return res.json();\n};\n\nfunction latestValue(resp: TimeseriesResponse | undefined): number | undefined {\n const points = resp?.points;\n if (!points || points.length === 0) return undefined;\n return points[points.length - 1]?.value;\n}\n\nfunction toneClass(pct: number, [warn, danger]: [number, number]): string {\n if (pct >= danger) return \"bg-red-500\";\n if (pct >= warn) return \"bg-amber-500\";\n return \"bg-emerald-500\";\n}\n\nfunction CoreBarsIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return (\n <Icon\n name={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n }\n return (\n <Icon\n icon={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n}\n\nfunction formatCores(cores: number): string {\n return Number.isInteger(cores) ? String(cores) : cores.toFixed(1);\n}\n\n/**\n * TimeseriesCoreBars renders CPU utilisation as a row of vertical bars — one bar\n * per core (the ceiling of the CPU limit) — filled left to right by the latest\n * usage. The bar that straddles the usage boundary is partially filled (\"blocked\n * out\") to show the fractional core in use, and the trailing bars stay empty to\n * show headroom. Both usage and limit are read live from the timeseries store,\n * mirroring TimeseriesGauge's data plumbing; the bar colour crosses warning and\n * danger thresholds. A \"<used> / <cores>\" caption sits below with the icon+title.\n */\nexport function TimeseriesCoreBars({\n baseUrl = \"\",\n value,\n max,\n unit,\n title,\n icon,\n range = \"1h\",\n refreshMs = 5000,\n thresholds = [75, 90],\n variant = \"default\",\n showLabel = true,\n showValue = true,\n showCapacity = false,\n orientation,\n hoverCard = true,\n fetcher = defaultFetcher,\n className,\n}: TimeseriesCoreBarsProps) {\n const perBar = unit?.perBar ?? 1000;\n const unitLabel = unit?.label ?? \"cores\";\n const barLabel = unit?.barLabel ?? \"core\";\n const formatUnits = unit?.format ?? formatCores;\n const maxIsSeries = typeof max === \"object\";\n const maxSeries = maxIsSeries ? max : undefined;\n const ids = useMemo(() => {\n const list = [value.id];\n if (maxSeries) list.push(maxSeries.id);\n return list;\n }, [value.id, maxSeries]);\n\n const results = useQueries({\n queries: ids.map((id) => {\n const u = new URL(baseUrl + id, window.location.origin);\n if (range) u.searchParams.set(\"since\", range);\n const requestUrl = u.pathname + u.search;\n return {\n queryKey: [\"timeseries\", requestUrl],\n queryFn: () => fetcher(requestUrl),\n refetchInterval: refreshMs > 0 ? refreshMs : false,\n staleTime: 0,\n retry: 0,\n };\n }),\n });\n\n const rawValue = latestValue(results[0]?.data);\n const usage =\n rawValue === undefined\n ? undefined\n : value.transform\n ? value.transform(rawValue)\n : rawValue;\n\n let limit: number | undefined;\n if (typeof max === \"number\") {\n limit = max;\n } else if (maxSeries) {\n const rawMax = latestValue(results[1]?.data);\n limit =\n rawMax === undefined\n ? undefined\n : maxSeries.transform\n ? maxSeries.transform(rawMax)\n : rawMax;\n }\n\n const model = deriveCoreBars(usage, limit, perBar);\n const tone = toneClass(model.pct, thresholds);\n const usageText = formatUnits(model.usageCores);\n const capacityText =\n model.limitCores !== undefined ? formatUnits(model.limitCores) : \"?\";\n const caption = !model.hasUsage\n ? \"—\"\n : showCapacity\n ? `${usageText} / ${capacityText} ${unitLabel}`\n : `${usageText} ${unitLabel}`;\n const compactCaption = !model.hasUsage\n ? \"—\"\n : showCapacity\n ? `${usageText}/${capacityText} ${unitLabel}`\n : `${usageText} ${unitLabel}`;\n const titleText = `${title}: ${compactCaption}`;\n const isCell = variant === \"cell\";\n\n // Hover card: reduce the fetched points to current/min/max/avg in bar-units\n // (raw value transformed, then divided by perBar) so they read in the same unit\n // as the caption. A bounded reading colours the current row by its threshold.\n const pctTone =\n model.limitCores === undefined\n ? undefined\n : model.pct >= thresholds[1]\n ? \"text-red-500\"\n : model.pct >= thresholds[0]\n ? \"text-amber-500\"\n : \"text-emerald-500\";\n const stats = seriesStats(results[0]?.data?.points, (v) =>\n (value.transform ? value.transform(v) : v) / perBar,\n );\n const fmt = (n: number) => `${formatUnits(n)} ${unitLabel}`;\n const hoverRows: GaugeHoverRow[] = model.hasUsage\n ? [\n { label: \"Current\", value: fmt(model.usageCores), ...(pctTone ? { tone: pctTone } : {}) },\n ...(stats\n ? [\n { label: \"Min\", value: fmt(stats.min) },\n { label: \"Max\", value: fmt(stats.max) },\n { label: \"Avg\", value: fmt(stats.avg) },\n ]\n : []),\n ...(model.limitCores !== undefined\n ? [{ label: \"Capacity\", value: fmt(model.limitCores) }]\n : []),\n ]\n : [];\n\n const resolvedOrientation = orientation ?? \"vertical\";\n const isDense = model.coreCount > 4;\n const valueText = isCell ? compactCaption : caption;\n const hiddenAccessibleText = !showLabel || !showValue ? titleText : undefined;\n const bars = (\n <span\n className={cn(\n \"flex shrink-0\",\n resolvedOrientation === \"vertical\"\n ? cn(\"items-end\", isCell ? \"h-4 gap-px\" : \"h-10 gap-0.5\")\n : cn(\n \"flex-col justify-center\",\n isCell ? \"h-4 w-10 gap-px\" : \"h-10 w-16 gap-0.5\",\n ),\n )}\n aria-hidden={isCell ? \"true\" : undefined}\n data-orientation={resolvedOrientation}\n data-core-count={model.coreCount}\n data-core-density={isDense ? \"compact\" : \"default\"}\n >\n {model.bars.map((bar, i) => {\n const corePct = Math.round(bar.fill * 100);\n return (\n <span\n key={i}\n className={cn(\n \"relative overflow-hidden bg-muted\",\n resolvedOrientation === \"vertical\"\n ? cn(\n \"h-full\",\n isCell\n ? isDense\n ? \"w-[3px] rounded-[2px]\"\n : \"w-1.5 rounded-[2px]\"\n : isDense\n ? \"w-1 rounded-sm\"\n : \"w-2 rounded-sm\",\n )\n : cn(\"min-h-px w-full flex-1 rounded-[2px]\"),\n )}\n title={`${barLabel} ${i + 1}: ${corePct}%`}\n aria-label={!isCell ? `${barLabel} ${i + 1}: ${corePct}%` : undefined}\n data-fill={bar.fill}\n >\n <span\n className={cn(\n \"absolute bottom-0 left-0 transition-all duration-300\",\n tone,\n )}\n style={\n resolvedOrientation === \"vertical\"\n ? { height: `${corePct}%`, right: 0 }\n : { width: `${corePct}%`, top: 0 }\n }\n />\n </span>\n );\n })}\n </span>\n );\n const valueNode = showValue ? (\n <span\n className={cn(\n \"shrink-0 font-semibold tabular-nums text-foreground\",\n isCell ? null : \"text-xs\",\n )}\n >\n {valueText}\n </span>\n ) : null;\n const label =\n icon || showLabel ? (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1 text-xs text-muted-foreground\",\n )}\n >\n {icon ? <CoreBarsIcon icon={icon} /> : null}\n {showLabel ? <span className=\"min-w-0 truncate\">{title}</span> : null}\n </span>\n ) : null;\n\n const useHover = hoverCard && hoverRows.length > 0;\n const footer = `over last ${range}`;\n\n if (isCell) {\n const cell = (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs\",\n className,\n )}\n {...(useHover ? {} : { title: titleText })}\n aria-label={useHover ? titleText : hiddenAccessibleText}\n >\n {label}\n {bars}\n {valueNode}\n </span>\n );\n return useHover ? (\n <GaugeHoverCard title={title} rows={hoverRows} footer={footer} trigger={cell} />\n ) : (\n cell\n );\n }\n\n const block = (\n <div\n className={cn(\"flex flex-col items-center gap-1\", className)}\n {...(useHover ? {} : { title: hiddenAccessibleText })}\n aria-label={useHover ? titleText : hiddenAccessibleText}\n >\n {bars}\n {valueNode}\n {label}\n </div>\n );\n return useHover ? (\n <GaugeHoverCard\n title={title}\n rows={hoverRows}\n footer={footer}\n trigger={block}\n className=\"w-full justify-center\"\n />\n ) : (\n block\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const clamp01 = (n) => Math.min(1, Math.max(0, n));
4
- function deriveCoreBars(usageMilli, limitMilli) {
5
- const hasUsage = usageMilli !== void 0;
6
- const usageCores = (usageMilli ?? 0) / 1e3;
7
- const hasLimit = limitMilli !== void 0 && limitMilli > 0;
8
- const limitCores = hasLimit ? limitMilli / 1e3 : void 0;
4
+ function deriveCoreBars(usage, limit, perBar = 1e3) {
5
+ const hasUsage = usage !== void 0;
6
+ const usageCores = (usage ?? 0) / perBar;
7
+ const hasLimit = limit !== void 0 && limit > 0;
8
+ const limitCores = hasLimit ? limit / perBar : void 0;
9
9
  const coreCount = Math.max(
10
10
  1,
11
11
  Math.ceil(hasLimit ? limitCores : usageCores)
@@ -1 +1 @@
1
- {"version":3,"file":"TimeseriesCoreBars.model.cjs","sources":["../../src/data/TimeseriesCoreBars.model.ts"],"sourcesContent":["export interface CoreBar {\n /** Fraction of this core that is in use, in [0, 1]. */\n fill: number;\n}\n\nexport interface CoreBarsModel {\n /** Whether a usage reading was available. */\n hasUsage: boolean;\n /** Usage expressed in cores (millicores / 1000). */\n usageCores: number;\n /** Capacity in cores; undefined when no limit was resolved. */\n limitCores?: number;\n /** Number of bars rendered (one per core). */\n coreCount: number;\n /** Utilisation percentage of capacity; 0 when unbounded. */\n pct: number;\n /** Per-core fill fractions, left to right. */\n bars: CoreBar[];\n}\n\nconst clamp01 = (n: number): number => Math.min(1, Math.max(0, n));\n\n// deriveCoreBars turns the latest usage/limit millicore readings into a per-core\n// bar model: one bar per core (ceil of the limit), filled left to right by usage\n// so the bar straddling the usage boundary is partially filled and the remainder\n// stays empty. When the limit is missing or 0 the bar count falls back to the\n// ceiling of the usage so an unbounded reading still renders sensibly.\nexport function deriveCoreBars(\n usageMilli: number | undefined,\n limitMilli: number | undefined,\n): CoreBarsModel {\n const hasUsage = usageMilli !== undefined;\n const usageCores = (usageMilli ?? 0) / 1000;\n const hasLimit = limitMilli !== undefined && limitMilli > 0;\n const limitCores = hasLimit ? (limitMilli as number) / 1000 : undefined;\n\n const coreCount = Math.max(\n 1,\n Math.ceil(hasLimit ? (limitCores as number) : usageCores),\n );\n const pct = hasLimit\n ? Math.min(100, Math.round((usageCores / (limitCores as number)) * 100))\n : 0;\n\n const bars: CoreBar[] = Array.from({ length: coreCount }, (_, i) => ({\n fill: clamp01(usageCores - i),\n }));\n\n return {\n hasUsage,\n usageCores,\n coreCount,\n pct,\n bars,\n ...(limitCores !== undefined && { limitCores }),\n };\n}\n"],"names":[],"mappings":";;AAoBA,MAAM,UAAU,CAAC,MAAsB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAO1D,SAAS,eACd,YACA,YACe;AACf,QAAM,WAAW,eAAe;AAChC,QAAM,cAAc,cAAc,KAAK;AACvC,QAAM,WAAW,eAAe,UAAa,aAAa;AAC1D,QAAM,aAAa,WAAY,aAAwB,MAAO;AAE9D,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA,KAAK,KAAK,WAAY,aAAwB,UAAU;AAAA,EAAA;AAE1D,QAAM,MAAM,WACR,KAAK,IAAI,KAAK,KAAK,MAAO,aAAc,aAAyB,GAAG,CAAC,IACrE;AAEJ,QAAM,OAAkB,MAAM,KAAK,EAAE,QAAQ,UAAA,GAAa,CAAC,GAAG,OAAO;AAAA,IACnE,MAAM,QAAQ,aAAa,CAAC;AAAA,EAAA,EAC5B;AAEF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,eAAe,UAAa,EAAE,WAAA;AAAA,EAAW;AAEjD;;"}
1
+ {"version":3,"file":"TimeseriesCoreBars.model.cjs","sources":["../../src/data/TimeseriesCoreBars.model.ts"],"sourcesContent":["export interface CoreBar {\n /** Fraction of this core that is in use, in [0, 1]. */\n fill: number;\n}\n\nexport interface CoreBarsModel {\n /** Whether a usage reading was available. */\n hasUsage: boolean;\n /** Usage expressed in bar-units (raw / perBar). */\n usageCores: number;\n /** Capacity in bar-units; undefined when no limit was resolved. */\n limitCores?: number;\n /** Number of bars rendered (one per bar-unit of capacity). */\n coreCount: number;\n /** Utilisation percentage of capacity; 0 when unbounded. */\n pct: number;\n /** Per-core fill fractions, left to right. */\n bars: CoreBar[];\n}\n\nconst clamp01 = (n: number): number => Math.min(1, Math.max(0, n));\n\n// deriveCoreBars turns the latest usage/limit readings into a per-bar model: one\n// bar per unit of capacity (ceil of the limit), filled left to right by usage so\n// the bar straddling the usage boundary is partially filled and the remainder\n// stays empty. When the limit is missing or 0 the bar count falls back to the\n// ceiling of the usage so an unbounded reading still renders sensibly. `perBar`\n// is the raw value that fills one bar (default 1000 = millicores per core); pass\n// e.g. 1 GiB to render one bar per gigabyte of memory.\nexport function deriveCoreBars(\n usage: number | undefined,\n limit: number | undefined,\n perBar = 1000,\n): CoreBarsModel {\n const hasUsage = usage !== undefined;\n const usageCores = (usage ?? 0) / perBar;\n const hasLimit = limit !== undefined && limit > 0;\n const limitCores = hasLimit ? (limit as number) / perBar : undefined;\n\n const coreCount = Math.max(\n 1,\n Math.ceil(hasLimit ? (limitCores as number) : usageCores),\n );\n const pct = hasLimit\n ? Math.min(100, Math.round((usageCores / (limitCores as number)) * 100))\n : 0;\n\n const bars: CoreBar[] = Array.from({ length: coreCount }, (_, i) => ({\n fill: clamp01(usageCores - i),\n }));\n\n return {\n hasUsage,\n usageCores,\n coreCount,\n pct,\n bars,\n ...(limitCores !== undefined && { limitCores }),\n };\n}\n"],"names":[],"mappings":";;AAoBA,MAAM,UAAU,CAAC,MAAsB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAS1D,SAAS,eACd,OACA,OACA,SAAS,KACM;AACf,QAAM,WAAW,UAAU;AAC3B,QAAM,cAAc,SAAS,KAAK;AAClC,QAAM,WAAW,UAAU,UAAa,QAAQ;AAChD,QAAM,aAAa,WAAY,QAAmB,SAAS;AAE3D,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA,KAAK,KAAK,WAAY,aAAwB,UAAU;AAAA,EAAA;AAE1D,QAAM,MAAM,WACR,KAAK,IAAI,KAAK,KAAK,MAAO,aAAc,aAAyB,GAAG,CAAC,IACrE;AAEJ,QAAM,OAAkB,MAAM,KAAK,EAAE,QAAQ,UAAA,GAAa,CAAC,GAAG,OAAO;AAAA,IACnE,MAAM,QAAQ,aAAa,CAAC;AAAA,EAAA,EAC5B;AAEF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,eAAe,UAAa,EAAE,WAAA;AAAA,EAAW;AAEjD;;"}
@@ -5,16 +5,16 @@ export interface CoreBar {
5
5
  export interface CoreBarsModel {
6
6
  /** Whether a usage reading was available. */
7
7
  hasUsage: boolean;
8
- /** Usage expressed in cores (millicores / 1000). */
8
+ /** Usage expressed in bar-units (raw / perBar). */
9
9
  usageCores: number;
10
- /** Capacity in cores; undefined when no limit was resolved. */
10
+ /** Capacity in bar-units; undefined when no limit was resolved. */
11
11
  limitCores?: number;
12
- /** Number of bars rendered (one per core). */
12
+ /** Number of bars rendered (one per bar-unit of capacity). */
13
13
  coreCount: number;
14
14
  /** Utilisation percentage of capacity; 0 when unbounded. */
15
15
  pct: number;
16
16
  /** Per-core fill fractions, left to right. */
17
17
  bars: CoreBar[];
18
18
  }
19
- export declare function deriveCoreBars(usageMilli: number | undefined, limitMilli: number | undefined): CoreBarsModel;
19
+ export declare function deriveCoreBars(usage: number | undefined, limit: number | undefined, perBar?: number): CoreBarsModel;
20
20
  //# sourceMappingURL=TimeseriesCoreBars.model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeseriesCoreBars.model.d.ts","sourceRoot":"","sources":["../../src/data/TimeseriesCoreBars.model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AASD,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,aAAa,CA0Bf"}
1
+ {"version":3,"file":"TimeseriesCoreBars.model.d.ts","sourceRoot":"","sources":["../../src/data/TimeseriesCoreBars.model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AAWD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,SAAO,GACZ,aAAa,CA0Bf"}
@@ -1,9 +1,9 @@
1
1
  const clamp01 = (n) => Math.min(1, Math.max(0, n));
2
- function deriveCoreBars(usageMilli, limitMilli) {
3
- const hasUsage = usageMilli !== void 0;
4
- const usageCores = (usageMilli ?? 0) / 1e3;
5
- const hasLimit = limitMilli !== void 0 && limitMilli > 0;
6
- const limitCores = hasLimit ? limitMilli / 1e3 : void 0;
2
+ function deriveCoreBars(usage, limit, perBar = 1e3) {
3
+ const hasUsage = usage !== void 0;
4
+ const usageCores = (usage ?? 0) / perBar;
5
+ const hasLimit = limit !== void 0 && limit > 0;
6
+ const limitCores = hasLimit ? limit / perBar : void 0;
7
7
  const coreCount = Math.max(
8
8
  1,
9
9
  Math.ceil(hasLimit ? limitCores : usageCores)
@@ -1 +1 @@
1
- {"version":3,"file":"TimeseriesCoreBars.model.js","sources":["../../src/data/TimeseriesCoreBars.model.ts"],"sourcesContent":["export interface CoreBar {\n /** Fraction of this core that is in use, in [0, 1]. */\n fill: number;\n}\n\nexport interface CoreBarsModel {\n /** Whether a usage reading was available. */\n hasUsage: boolean;\n /** Usage expressed in cores (millicores / 1000). */\n usageCores: number;\n /** Capacity in cores; undefined when no limit was resolved. */\n limitCores?: number;\n /** Number of bars rendered (one per core). */\n coreCount: number;\n /** Utilisation percentage of capacity; 0 when unbounded. */\n pct: number;\n /** Per-core fill fractions, left to right. */\n bars: CoreBar[];\n}\n\nconst clamp01 = (n: number): number => Math.min(1, Math.max(0, n));\n\n// deriveCoreBars turns the latest usage/limit millicore readings into a per-core\n// bar model: one bar per core (ceil of the limit), filled left to right by usage\n// so the bar straddling the usage boundary is partially filled and the remainder\n// stays empty. When the limit is missing or 0 the bar count falls back to the\n// ceiling of the usage so an unbounded reading still renders sensibly.\nexport function deriveCoreBars(\n usageMilli: number | undefined,\n limitMilli: number | undefined,\n): CoreBarsModel {\n const hasUsage = usageMilli !== undefined;\n const usageCores = (usageMilli ?? 0) / 1000;\n const hasLimit = limitMilli !== undefined && limitMilli > 0;\n const limitCores = hasLimit ? (limitMilli as number) / 1000 : undefined;\n\n const coreCount = Math.max(\n 1,\n Math.ceil(hasLimit ? (limitCores as number) : usageCores),\n );\n const pct = hasLimit\n ? Math.min(100, Math.round((usageCores / (limitCores as number)) * 100))\n : 0;\n\n const bars: CoreBar[] = Array.from({ length: coreCount }, (_, i) => ({\n fill: clamp01(usageCores - i),\n }));\n\n return {\n hasUsage,\n usageCores,\n coreCount,\n pct,\n bars,\n ...(limitCores !== undefined && { limitCores }),\n };\n}\n"],"names":[],"mappings":"AAoBA,MAAM,UAAU,CAAC,MAAsB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAO1D,SAAS,eACd,YACA,YACe;AACf,QAAM,WAAW,eAAe;AAChC,QAAM,cAAc,cAAc,KAAK;AACvC,QAAM,WAAW,eAAe,UAAa,aAAa;AAC1D,QAAM,aAAa,WAAY,aAAwB,MAAO;AAE9D,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA,KAAK,KAAK,WAAY,aAAwB,UAAU;AAAA,EAAA;AAE1D,QAAM,MAAM,WACR,KAAK,IAAI,KAAK,KAAK,MAAO,aAAc,aAAyB,GAAG,CAAC,IACrE;AAEJ,QAAM,OAAkB,MAAM,KAAK,EAAE,QAAQ,UAAA,GAAa,CAAC,GAAG,OAAO;AAAA,IACnE,MAAM,QAAQ,aAAa,CAAC;AAAA,EAAA,EAC5B;AAEF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,eAAe,UAAa,EAAE,WAAA;AAAA,EAAW;AAEjD;"}
1
+ {"version":3,"file":"TimeseriesCoreBars.model.js","sources":["../../src/data/TimeseriesCoreBars.model.ts"],"sourcesContent":["export interface CoreBar {\n /** Fraction of this core that is in use, in [0, 1]. */\n fill: number;\n}\n\nexport interface CoreBarsModel {\n /** Whether a usage reading was available. */\n hasUsage: boolean;\n /** Usage expressed in bar-units (raw / perBar). */\n usageCores: number;\n /** Capacity in bar-units; undefined when no limit was resolved. */\n limitCores?: number;\n /** Number of bars rendered (one per bar-unit of capacity). */\n coreCount: number;\n /** Utilisation percentage of capacity; 0 when unbounded. */\n pct: number;\n /** Per-core fill fractions, left to right. */\n bars: CoreBar[];\n}\n\nconst clamp01 = (n: number): number => Math.min(1, Math.max(0, n));\n\n// deriveCoreBars turns the latest usage/limit readings into a per-bar model: one\n// bar per unit of capacity (ceil of the limit), filled left to right by usage so\n// the bar straddling the usage boundary is partially filled and the remainder\n// stays empty. When the limit is missing or 0 the bar count falls back to the\n// ceiling of the usage so an unbounded reading still renders sensibly. `perBar`\n// is the raw value that fills one bar (default 1000 = millicores per core); pass\n// e.g. 1 GiB to render one bar per gigabyte of memory.\nexport function deriveCoreBars(\n usage: number | undefined,\n limit: number | undefined,\n perBar = 1000,\n): CoreBarsModel {\n const hasUsage = usage !== undefined;\n const usageCores = (usage ?? 0) / perBar;\n const hasLimit = limit !== undefined && limit > 0;\n const limitCores = hasLimit ? (limit as number) / perBar : undefined;\n\n const coreCount = Math.max(\n 1,\n Math.ceil(hasLimit ? (limitCores as number) : usageCores),\n );\n const pct = hasLimit\n ? Math.min(100, Math.round((usageCores / (limitCores as number)) * 100))\n : 0;\n\n const bars: CoreBar[] = Array.from({ length: coreCount }, (_, i) => ({\n fill: clamp01(usageCores - i),\n }));\n\n return {\n hasUsage,\n usageCores,\n coreCount,\n pct,\n bars,\n ...(limitCores !== undefined && { limitCores }),\n };\n}\n"],"names":[],"mappings":"AAoBA,MAAM,UAAU,CAAC,MAAsB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAS1D,SAAS,eACd,OACA,OACA,SAAS,KACM;AACf,QAAM,WAAW,UAAU;AAC3B,QAAM,cAAc,SAAS,KAAK;AAClC,QAAM,WAAW,UAAU,UAAa,QAAQ;AAChD,QAAM,aAAa,WAAY,QAAmB,SAAS;AAE3D,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA,KAAK,KAAK,WAAY,aAAwB,UAAU;AAAA,EAAA;AAE1D,QAAM,MAAM,WACR,KAAK,IAAI,KAAK,KAAK,MAAO,aAAc,aAAyB,GAAG,CAAC,IACrE;AAEJ,QAAM,OAAkB,MAAM,KAAK,EAAE,QAAQ,UAAA,GAAa,CAAC,GAAG,OAAO;AAAA,IACnE,MAAM,QAAQ,aAAa,CAAC;AAAA,EAAA,EAC5B;AAEF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,eAAe,UAAa,EAAE,WAAA;AAAA,EAAW;AAEjD;"}
@@ -8,6 +8,8 @@ const format = require("../lib/format.cjs");
8
8
  const Modal = require("../overlay/Modal.cjs");
9
9
  const Icon = require("./Icon.cjs");
10
10
  const TimeseriesPanel = require("./TimeseriesPanel.cjs");
11
+ const GaugeHoverCard = require("./GaugeHoverCard.cjs");
12
+ const gaugeStats = require("./gauge-stats.cjs");
11
13
  const UiFullscreen = require("../icons/components/UiFullscreen.cjs");
12
14
  const defaultFetcher = async (url) => {
13
15
  const res = await fetch(url);
@@ -22,6 +24,38 @@ function toneClass(pct, [warn, danger]) {
22
24
  if (pct >= warn) return "text-amber-500";
23
25
  return "text-emerald-500";
24
26
  }
27
+ function toneBgClass(pct, [warn, danger]) {
28
+ if (pct >= danger) return "bg-red-500";
29
+ if (pct >= warn) return "bg-amber-500";
30
+ return "bg-emerald-500";
31
+ }
32
+ function GaugeArc({ pct, tone, strokeWidth }) {
33
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 100 50", className: "h-full w-full overflow-visible", children: [
34
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: GAUGE_PATH, fill: "none", stroke: "currentColor", strokeWidth, strokeLinecap: "round", className: "text-muted" }),
35
+ /* @__PURE__ */ jsxRuntime.jsx(
36
+ "path",
37
+ {
38
+ d: GAUGE_PATH,
39
+ fill: "none",
40
+ stroke: "currentColor",
41
+ strokeWidth,
42
+ strokeLinecap: "round",
43
+ className: tone,
44
+ strokeDasharray: GAUGE_ARC,
45
+ strokeDashoffset: GAUGE_ARC * (1 - pct / 100)
46
+ }
47
+ )
48
+ ] });
49
+ }
50
+ function GaugeBar({ pct, toneBg, className }) {
51
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils.cn("relative block overflow-hidden rounded-full bg-muted", className), "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(
52
+ "span",
53
+ {
54
+ className: utils.cn("absolute inset-y-0 left-0 rounded-full transition-all duration-300", toneBg),
55
+ style: { width: `${pct}%` }
56
+ }
57
+ ) });
58
+ }
25
59
  function latestValue(resp) {
26
60
  var _a;
27
61
  const points = resp == null ? void 0 : resp.points;
@@ -47,11 +81,13 @@ function TimeseriesGauge({
47
81
  thresholds = [75, 90],
48
82
  centerDisplay = "value",
49
83
  variant = "default",
84
+ shape = "radial",
50
85
  showLabel = true,
86
+ hoverCard = true,
51
87
  fetcher = defaultFetcher,
52
88
  className
53
89
  }) {
54
- var _a, _b;
90
+ var _a, _b, _c, _d;
55
91
  const [expanded, setExpanded] = react.useState(false);
56
92
  const maxIsSeries = typeof max === "object";
57
93
  const maxSeries = maxIsSeries ? max : void 0;
@@ -87,6 +123,7 @@ function TimeseriesGauge({
87
123
  const bounded = hasValue && limit !== void 0 && limit > 0;
88
124
  const pct = bounded ? Math.min(100, Math.round(usage / limit * 100)) : 0;
89
125
  const tone = toneClass(pct, thresholds);
126
+ const toneBg = toneBgClass(pct, thresholds);
90
127
  const readout = centerDisplay === "percent" ? bounded ? `${pct}%` : hasValue ? "n/a" : "—" : hasValue ? format.formatUnit(usage, unit) : "—";
91
128
  const titleText = `${title}: ${readout}`;
92
129
  const canExpand = expandable && variant === "default";
@@ -96,74 +133,63 @@ function TimeseriesGauge({
96
133
  if (maxSeries) s.push({ id: maxSeries.id, label: "max", ...maxSeries.transform ? { transform: maxSeries.transform } : {} });
97
134
  return s;
98
135
  }, [value.id, value.transform, maxSeries]);
136
+ const stats = gaugeStats.seriesStats((_d = (_c = results[0]) == null ? void 0 : _c.data) == null ? void 0 : _d.points, value.transform);
137
+ const fmt = (n) => format.formatUnit(n, unit);
138
+ const hoverRows = hasValue ? [
139
+ { label: "Current", value: fmt(usage), ...bounded ? { tone } : {} },
140
+ ...stats ? [
141
+ { label: "Min", value: fmt(stats.min) },
142
+ { label: "Max", value: fmt(stats.max) },
143
+ { label: "Avg", value: fmt(stats.avg) }
144
+ ] : [],
145
+ ...limit !== void 0 ? [{ label: "Capacity", value: fmt(limit) }] : []
146
+ ] : [];
147
+ const useHover = hoverCard && hoverRows.length > 0;
148
+ const footer = `over last ${range}`;
99
149
  if (variant === "cell") {
100
- return /* @__PURE__ */ jsxRuntime.jsxs(
150
+ const cell = /* @__PURE__ */ jsxRuntime.jsxs(
101
151
  "span",
102
152
  {
103
153
  className: utils.cn(
104
154
  "inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs",
105
155
  className
106
156
  ),
107
- title: titleText,
108
- "aria-label": !showLabel ? titleText : void 0,
157
+ ...useHover ? {} : { title: titleText },
158
+ "aria-label": useHover || !showLabel ? titleText : void 0,
159
+ "data-shape": shape,
109
160
  children: [
110
161
  icon ? /* @__PURE__ */ jsxRuntime.jsx(GaugeIcon, { icon }) : null,
111
162
  showLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate text-muted-foreground", children: title }) : null,
112
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative h-4 w-8 shrink-0", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 100 50", className: "h-full w-full overflow-visible", children: [
113
- /* @__PURE__ */ jsxRuntime.jsx(
114
- "path",
115
- {
116
- d: GAUGE_PATH,
117
- fill: "none",
118
- stroke: "currentColor",
119
- strokeWidth: 10,
120
- strokeLinecap: "round",
121
- className: "text-muted"
122
- }
123
- ),
124
- /* @__PURE__ */ jsxRuntime.jsx(
125
- "path",
126
- {
127
- d: GAUGE_PATH,
128
- fill: "none",
129
- stroke: "currentColor",
130
- strokeWidth: 10,
131
- strokeLinecap: "round",
132
- className: tone,
133
- strokeDasharray: GAUGE_ARC,
134
- strokeDashoffset: GAUGE_ARC * (1 - pct / 100)
135
- }
136
- )
137
- ] }) }),
163
+ shape === "linear" ? /* @__PURE__ */ jsxRuntime.jsx(GaugeBar, { pct, toneBg, className: "h-1.5 w-12 shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative h-4 w-8 shrink-0", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(GaugeArc, { pct, tone, strokeWidth: 10 }) }),
138
164
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: utils.cn("shrink-0 font-semibold tabular-nums", readoutTone), children: readout })
139
165
  ]
140
166
  }
141
167
  );
168
+ return useHover ? /* @__PURE__ */ jsxRuntime.jsx(GaugeHoverCard.GaugeHoverCard, { title, rows: hoverRows, footer, trigger: cell }) : cell;
142
169
  }
143
- return /* @__PURE__ */ jsxRuntime.jsxs(
170
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(
144
171
  "div",
145
172
  {
146
173
  className: utils.cn("flex flex-col items-center gap-1", className),
147
- title: !showLabel ? titleText : void 0,
148
- "aria-label": !showLabel ? titleText : void 0,
174
+ ...useHover ? {} : { title: !showLabel ? titleText : void 0 },
175
+ "aria-label": useHover || !showLabel ? titleText : void 0,
176
+ "data-shape": shape,
149
177
  children: [
150
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-10 w-20", children: [
151
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 100 50", className: "h-full w-full overflow-visible", children: [
152
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: GAUGE_PATH, fill: "none", stroke: "currentColor", strokeWidth: 9, strokeLinecap: "round", className: "text-muted" }),
153
- /* @__PURE__ */ jsxRuntime.jsx(
154
- "path",
155
- {
156
- d: GAUGE_PATH,
157
- fill: "none",
158
- stroke: "currentColor",
159
- strokeWidth: 9,
160
- strokeLinecap: "round",
161
- className: tone,
162
- strokeDasharray: GAUGE_ARC,
163
- strokeDashoffset: GAUGE_ARC * (1 - pct / 100)
164
- }
165
- )
166
- ] }),
178
+ shape === "linear" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2", children: [
179
+ /* @__PURE__ */ jsxRuntime.jsx(GaugeBar, { pct, toneBg, className: "h-2 w-full" }),
180
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-sm font-semibold text-foreground", children: readout }),
181
+ canExpand && /* @__PURE__ */ jsxRuntime.jsx(
182
+ "button",
183
+ {
184
+ type: "button",
185
+ "aria-label": "Expand chart",
186
+ onClick: () => setExpanded(true),
187
+ className: "shrink-0 text-muted-foreground hover:text-foreground",
188
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiFullscreen.UiFullscreen, width: 12, height: 12 })
189
+ }
190
+ )
191
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-10 w-20", children: [
192
+ /* @__PURE__ */ jsxRuntime.jsx(GaugeArc, { pct, tone, strokeWidth: 9 }),
167
193
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-x-0 bottom-0 text-center text-sm font-semibold text-foreground", children: readout }),
168
194
  canExpand && /* @__PURE__ */ jsxRuntime.jsx(
169
195
  "button",
@@ -179,24 +205,36 @@ function TimeseriesGauge({
179
205
  icon || showLabel ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [
180
206
  icon ? /* @__PURE__ */ jsxRuntime.jsx(GaugeIcon, { icon }) : null,
181
207
  showLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: title }) : null
182
- ] }) : null,
183
- canExpand && /* @__PURE__ */ jsxRuntime.jsx(Modal.Modal, { open: expanded, onClose: () => setExpanded(false), title, size: "xl", children: /* @__PURE__ */ jsxRuntime.jsx(
184
- TimeseriesPanel.TimeseriesPanel,
185
- {
186
- title,
187
- ...icon ? { icon } : {},
188
- ...unit ? { unit } : {},
189
- baseUrl,
190
- series: chartSeries,
191
- range,
192
- refreshMs,
193
- expandable: false,
194
- fetcher
195
- }
196
- ) })
208
+ ] }) : null
197
209
  ]
198
210
  }
199
211
  );
212
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
213
+ useHover ? /* @__PURE__ */ jsxRuntime.jsx(
214
+ GaugeHoverCard.GaugeHoverCard,
215
+ {
216
+ title,
217
+ rows: hoverRows,
218
+ footer,
219
+ trigger: body,
220
+ className: "w-full justify-center"
221
+ }
222
+ ) : body,
223
+ canExpand && /* @__PURE__ */ jsxRuntime.jsx(Modal.Modal, { open: expanded, onClose: () => setExpanded(false), title, size: "xl", children: /* @__PURE__ */ jsxRuntime.jsx(
224
+ TimeseriesPanel.TimeseriesPanel,
225
+ {
226
+ title,
227
+ ...icon ? { icon } : {},
228
+ ...unit ? { unit } : {},
229
+ baseUrl,
230
+ series: chartSeries,
231
+ range,
232
+ refreshMs,
233
+ expandable: false,
234
+ fetcher
235
+ }
236
+ ) })
237
+ ] });
200
238
  }
201
239
  exports.TimeseriesGauge = TimeseriesGauge;
202
240
  //# sourceMappingURL=TimeseriesGauge.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeseriesGauge.cjs","sources":["../../src/data/TimeseriesGauge.tsx"],"sourcesContent":["import { useQueries } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { formatUnit } from \"../lib/format\";\nimport { Modal } from \"../overlay/Modal\";\nimport { UiFullscreen } from \"../icons\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport {\n TimeseriesPanel,\n type TimeseriesResponse,\n type TimeseriesSeries,\n} from \"./TimeseriesPanel\";\n\n/** A metric series whose latest value drives the gauge fill or its maximum. */\nexport interface GaugeSeries {\n /** Metric id appended to the gauge's baseUrl, e.g. \"k8s.statefulset.cycle.cpu.usage\". */\n id: string;\n /** Maps the latest value before display (e.g. unit scaling). Identity when omitted. */\n transform?: (value: number) => number;\n}\n\nexport type TimeseriesGaugeVariant = \"default\" | \"cell\";\n\nexport interface TimeseriesGaugeProps {\n /** Common prefix; the value/max requests are `baseUrl + id`. */\n baseUrl?: string;\n /** The metric whose latest value fills the gauge. */\n value: GaugeSeries;\n /**\n * The gauge maximum. Either a metric series (its latest value, e.g. a `.limit`\n * metric) or a fixed number. When omitted, or when the resolved max is 0, the\n * gauge shows the raw value with no fill (an unbounded reading).\n */\n max?: GaugeSeries | number;\n title: string;\n /** Iconify name or static icon component shown beside the label. */\n icon?: string | StaticIconComponent;\n /** Grafana-style unit key for the readout (e.g. \"bytes\", \"percent\", \"short\", \"ms\"). */\n unit?: string;\n /** Look-back window for the expand chart, passed as ?since=; defaults to \"1h\". */\n range?: string;\n /** Poll interval in ms; defaults to 5000. Pass 0 to disable polling. */\n refreshMs?: number;\n /** Show an expand button that opens the value/max time-series chart in a modal. Default true. */\n expandable?: boolean;\n /**\n * Utilisation thresholds (percent of max) at which the arc turns amber then\n * red. Defaults to [75, 90].\n */\n thresholds?: [warning: number, danger: number];\n /**\n * What to print in the centre: the formatted value (default) or the\n * utilisation percentage of max (e.g. CPU usage out of its millicore limit).\n */\n centerDisplay?: \"value\" | \"percent\";\n /** Visual density/layout. `cell` is a compact inline form for table/grid cells. */\n variant?: TimeseriesGaugeVariant;\n /** Show the title text. Icons and values remain visible when false. */\n showLabel?: boolean;\n /** Override the default fetch (e.g. to route through an app's API client). */\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nconst defaultFetcher = async (url: string): Promise<TimeseriesResponse> => {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);\n return res.json();\n};\n\n// Half-gauge SVG geometry: a 100×50 viewBox semicircle (radius 40, centre 50,50)\n// swept 180°. The arc length is π·r; stroke-dashoffset reveals value/max of it.\nconst GAUGE_RADIUS = 40;\nconst GAUGE_ARC = Math.PI * GAUGE_RADIUS;\nconst GAUGE_PATH = `M 10 50 A ${GAUGE_RADIUS} ${GAUGE_RADIUS} 0 0 1 90 50`;\n\nfunction toneClass(pct: number, [warn, danger]: [number, number]): string {\n if (pct >= danger) return \"text-red-500\";\n if (pct >= warn) return \"text-amber-500\";\n return \"text-emerald-500\";\n}\n\nfunction latestValue(resp: TimeseriesResponse | undefined): number | undefined {\n const points = resp?.points;\n if (!points || points.length === 0) return undefined;\n return points[points.length - 1]?.value;\n}\n\nfunction GaugeIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return <Icon name={icon} width={14} height={14} className=\"text-muted-foreground\" />;\n }\n return <Icon icon={icon} width={14} height={14} className=\"text-muted-foreground\" />;\n}\n\n/**\n * TimeseriesGauge renders a half (180°) radial gauge whose fill is the latest\n * value of a metric over its maximum (a `.limit`-style metric or a fixed number),\n * both read live from the timeseries store. The centre shows the utilisation\n * percentage, with the value/max caption below; the arc colour crosses warning\n * and danger thresholds. An expand button opens the full value/max time-series\n * chart in a modal (a `TimeseriesPanel`), so the gauge gives the at-a-glance\n * reading and the chart the trend.\n */\nexport function TimeseriesGauge({\n baseUrl = \"\",\n value,\n max,\n title,\n icon,\n unit,\n range = \"1h\",\n refreshMs = 5000,\n expandable = true,\n thresholds = [75, 90],\n centerDisplay = \"value\",\n variant = \"default\",\n showLabel = true,\n fetcher = defaultFetcher,\n className,\n}: TimeseriesGaugeProps) {\n const [expanded, setExpanded] = useState(false);\n\n const maxIsSeries = typeof max === \"object\";\n const maxSeries = maxIsSeries ? max : undefined;\n const ids = useMemo(() => {\n const list = [value.id];\n if (maxSeries) list.push(maxSeries.id);\n return list;\n }, [value.id, maxSeries]);\n\n const results = useQueries({\n queries: ids.map((id) => {\n const u = new URL(baseUrl + id, window.location.origin);\n if (range) u.searchParams.set(\"since\", range);\n const requestUrl = u.pathname + u.search;\n return {\n queryKey: [\"timeseries\", requestUrl],\n queryFn: () => fetcher(requestUrl),\n refetchInterval: refreshMs > 0 ? refreshMs : false,\n staleTime: 0,\n retry: 0,\n };\n }),\n });\n\n const rawValue = latestValue(results[0]?.data);\n const hasValue = rawValue !== undefined;\n const usage = value.transform ? value.transform(rawValue ?? 0) : (rawValue ?? 0);\n\n let limit: number | undefined;\n if (typeof max === \"number\") {\n limit = max;\n } else if (maxSeries) {\n const rawMax = latestValue(results[1]?.data);\n limit = rawMax === undefined ? undefined : maxSeries.transform ? maxSeries.transform(rawMax) : rawMax;\n }\n\n const bounded = hasValue && limit !== undefined && limit > 0;\n const pct = bounded ? Math.min(100, Math.round((usage / (limit as number)) * 100)) : 0;\n const tone = toneClass(pct, thresholds);\n const readout =\n centerDisplay === \"percent\"\n ? bounded\n ? `${pct}%`\n : hasValue\n ? \"n/a\"\n : \"—\"\n : hasValue\n ? formatUnit(usage, unit)\n : \"—\";\n const titleText = `${title}: ${readout}`;\n const canExpand = expandable && variant === \"default\";\n const readoutTone = bounded ? tone : \"text-foreground\";\n\n const chartSeries: TimeseriesSeries[] = useMemo(() => {\n const s: TimeseriesSeries[] = [{ id: value.id, label: \"value\", ...(value.transform ? { transform: value.transform } : {}) }];\n if (maxSeries) s.push({ id: maxSeries.id, label: \"max\", ...(maxSeries.transform ? { transform: maxSeries.transform } : {}) });\n return s;\n }, [value.id, value.transform, maxSeries]);\n\n if (variant === \"cell\") {\n return (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs\",\n className,\n )}\n title={titleText}\n aria-label={!showLabel ? titleText : undefined}\n >\n {icon ? <GaugeIcon icon={icon} /> : null}\n {showLabel ? <span className=\"min-w-0 truncate text-muted-foreground\">{title}</span> : null}\n <span className=\"relative h-4 w-8 shrink-0\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 100 50\" className=\"h-full w-full overflow-visible\">\n <path\n d={GAUGE_PATH}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={10}\n strokeLinecap=\"round\"\n className=\"text-muted\"\n />\n <path\n d={GAUGE_PATH}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={10}\n strokeLinecap=\"round\"\n className={tone}\n strokeDasharray={GAUGE_ARC}\n strokeDashoffset={GAUGE_ARC * (1 - pct / 100)}\n />\n </svg>\n </span>\n <span className={cn(\"shrink-0 font-semibold tabular-nums\", readoutTone)}>\n {readout}\n </span>\n </span>\n );\n }\n\n return (\n <div\n className={cn(\"flex flex-col items-center gap-1\", className)}\n title={!showLabel ? titleText : undefined}\n aria-label={!showLabel ? titleText : undefined}\n >\n <div className=\"relative h-10 w-20\">\n <svg viewBox=\"0 0 100 50\" className=\"h-full w-full overflow-visible\">\n <path d={GAUGE_PATH} fill=\"none\" stroke=\"currentColor\" strokeWidth={9} strokeLinecap=\"round\" className=\"text-muted\" />\n <path\n d={GAUGE_PATH}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={9}\n strokeLinecap=\"round\"\n className={tone}\n strokeDasharray={GAUGE_ARC}\n strokeDashoffset={GAUGE_ARC * (1 - pct / 100)}\n />\n </svg>\n <span className=\"absolute inset-x-0 bottom-0 text-center text-sm font-semibold text-foreground\">\n {readout}\n </span>\n {canExpand && (\n <button\n type=\"button\"\n aria-label=\"Expand chart\"\n onClick={() => setExpanded(true)}\n className=\"absolute right-0 top-0 text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={UiFullscreen} width={12} height={12} />\n </button>\n )}\n </div>\n {icon || showLabel ? (\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n {icon ? <GaugeIcon icon={icon} /> : null}\n {showLabel ? <span>{title}</span> : null}\n </div>\n ) : null}\n\n {canExpand && (\n <Modal open={expanded} onClose={() => setExpanded(false)} title={title} size=\"xl\">\n <TimeseriesPanel\n title={title}\n {...(icon ? { icon } : {})}\n {...(unit ? { unit } : {})}\n baseUrl={baseUrl}\n series={chartSeries}\n range={range}\n refreshMs={refreshMs}\n expandable={false}\n fetcher={fetcher}\n />\n </Modal>\n )}\n </div>\n );\n}\n"],"names":["jsx","Icon","useState","useMemo","useQueries","formatUnit","jsxs","cn","UiFullscreen","Modal","TimeseriesPanel"],"mappings":"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"}
1
+ {"version":3,"file":"TimeseriesGauge.cjs","sources":["../../src/data/TimeseriesGauge.tsx"],"sourcesContent":["import { useQueries } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { formatUnit } from \"../lib/format\";\nimport { Modal } from \"../overlay/Modal\";\nimport { UiFullscreen } from \"../icons\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport {\n TimeseriesPanel,\n type TimeseriesResponse,\n type TimeseriesSeries,\n} from \"./TimeseriesPanel\";\nimport { GaugeHoverCard, type GaugeHoverRow } from \"./GaugeHoverCard\";\nimport { seriesStats } from \"./gauge-stats\";\n\n/** A metric series whose latest value drives the gauge fill or its maximum. */\nexport interface GaugeSeries {\n /** Metric id appended to the gauge's baseUrl, e.g. \"k8s.statefulset.cycle.cpu.usage\". */\n id: string;\n /** Maps the latest value before display (e.g. unit scaling). Identity when omitted. */\n transform?: (value: number) => number;\n}\n\nexport type TimeseriesGaugeVariant = \"default\" | \"cell\";\n/** Gauge fill geometry: a half-circle arc (default) or a horizontal progress bar. */\nexport type TimeseriesGaugeShape = \"radial\" | \"linear\";\n\nexport interface TimeseriesGaugeProps {\n /** Common prefix; the value/max requests are `baseUrl + id`. */\n baseUrl?: string;\n /** The metric whose latest value fills the gauge. */\n value: GaugeSeries;\n /**\n * The gauge maximum. Either a metric series (its latest value, e.g. a `.limit`\n * metric) or a fixed number. When omitted, or when the resolved max is 0, the\n * gauge shows the raw value with no fill (an unbounded reading).\n */\n max?: GaugeSeries | number;\n title: string;\n /** Iconify name or static icon component shown beside the label. */\n icon?: string | StaticIconComponent;\n /** Grafana-style unit key for the readout (e.g. \"bytes\", \"percent\", \"short\", \"ms\"). */\n unit?: string;\n /** Look-back window for the expand chart, passed as ?since=; defaults to \"1h\". */\n range?: string;\n /** Poll interval in ms; defaults to 5000. Pass 0 to disable polling. */\n refreshMs?: number;\n /** Show an expand button that opens the value/max time-series chart in a modal. Default true. */\n expandable?: boolean;\n /**\n * Utilisation thresholds (percent of max) at which the arc turns amber then\n * red. Defaults to [75, 90].\n */\n thresholds?: [warning: number, danger: number];\n /**\n * What to print in the centre: the formatted value (default) or the\n * utilisation percentage of max (e.g. CPU usage out of its millicore limit).\n */\n centerDisplay?: \"value\" | \"percent\";\n /** Visual density/layout. `cell` is a compact inline form for table/grid cells. */\n variant?: TimeseriesGaugeVariant;\n /** Fill geometry: a radial half-gauge (default) or a horizontal progress bar. */\n shape?: TimeseriesGaugeShape;\n /** Show the title text. Icons and values remain visible when false. */\n showLabel?: boolean;\n /**\n * Wrap the gauge in a hover card summarising the metric (label + current / min /\n * max / avg / capacity over the window). Defaults to true.\n */\n hoverCard?: boolean;\n /** Override the default fetch (e.g. to route through an app's API client). */\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nconst defaultFetcher = async (url: string): Promise<TimeseriesResponse> => {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);\n return res.json();\n};\n\n// Half-gauge SVG geometry: a 100×50 viewBox semicircle (radius 40, centre 50,50)\n// swept 180°. The arc length is π·r; stroke-dashoffset reveals value/max of it.\nconst GAUGE_RADIUS = 40;\nconst GAUGE_ARC = Math.PI * GAUGE_RADIUS;\nconst GAUGE_PATH = `M 10 50 A ${GAUGE_RADIUS} ${GAUGE_RADIUS} 0 0 1 90 50`;\n\nfunction toneClass(pct: number, [warn, danger]: [number, number]): string {\n if (pct >= danger) return \"text-red-500\";\n if (pct >= warn) return \"text-amber-500\";\n return \"text-emerald-500\";\n}\n\n// toneBgClass mirrors toneClass for the linear bar's fill, which needs a\n// background colour rather than the arc's stroke (currentColor) tone.\nfunction toneBgClass(pct: number, [warn, danger]: [number, number]): string {\n if (pct >= danger) return \"bg-red-500\";\n if (pct >= warn) return \"bg-amber-500\";\n return \"bg-emerald-500\";\n}\n\n// GaugeArc is the half-circle SVG shared by the cell and default radial gauges;\n// only the stroke width differs between the two densities.\nfunction GaugeArc({ pct, tone, strokeWidth }: { pct: number; tone: string; strokeWidth: number }) {\n return (\n <svg viewBox=\"0 0 100 50\" className=\"h-full w-full overflow-visible\">\n <path d={GAUGE_PATH} fill=\"none\" stroke=\"currentColor\" strokeWidth={strokeWidth} strokeLinecap=\"round\" className=\"text-muted\" />\n <path\n d={GAUGE_PATH}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n className={tone}\n strokeDasharray={GAUGE_ARC}\n strokeDashoffset={GAUGE_ARC * (1 - pct / 100)}\n />\n </svg>\n );\n}\n\n// GaugeBar is the horizontal progress track shared by the cell and default linear\n// gauges; the caller sizes it via className (e.g. \"h-1.5 w-12\" or \"h-2 w-full\").\nfunction GaugeBar({ pct, toneBg, className }: { pct: number; toneBg: string; className?: string }) {\n return (\n <span className={cn(\"relative block overflow-hidden rounded-full bg-muted\", className)} aria-hidden=\"true\">\n <span\n className={cn(\"absolute inset-y-0 left-0 rounded-full transition-all duration-300\", toneBg)}\n style={{ width: `${pct}%` }}\n />\n </span>\n );\n}\n\nfunction latestValue(resp: TimeseriesResponse | undefined): number | undefined {\n const points = resp?.points;\n if (!points || points.length === 0) return undefined;\n return points[points.length - 1]?.value;\n}\n\nfunction GaugeIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return <Icon name={icon} width={14} height={14} className=\"text-muted-foreground\" />;\n }\n return <Icon icon={icon} width={14} height={14} className=\"text-muted-foreground\" />;\n}\n\n/**\n * TimeseriesGauge renders a half (180°) radial gauge whose fill is the latest\n * value of a metric over its maximum (a `.limit`-style metric or a fixed number),\n * both read live from the timeseries store. The centre shows the utilisation\n * percentage, with the value/max caption below; the arc colour crosses warning\n * and danger thresholds. An expand button opens the full value/max time-series\n * chart in a modal (a `TimeseriesPanel`), so the gauge gives the at-a-glance\n * reading and the chart the trend.\n */\nexport function TimeseriesGauge({\n baseUrl = \"\",\n value,\n max,\n title,\n icon,\n unit,\n range = \"1h\",\n refreshMs = 5000,\n expandable = true,\n thresholds = [75, 90],\n centerDisplay = \"value\",\n variant = \"default\",\n shape = \"radial\",\n showLabel = true,\n hoverCard = true,\n fetcher = defaultFetcher,\n className,\n}: TimeseriesGaugeProps) {\n const [expanded, setExpanded] = useState(false);\n\n const maxIsSeries = typeof max === \"object\";\n const maxSeries = maxIsSeries ? max : undefined;\n const ids = useMemo(() => {\n const list = [value.id];\n if (maxSeries) list.push(maxSeries.id);\n return list;\n }, [value.id, maxSeries]);\n\n const results = useQueries({\n queries: ids.map((id) => {\n const u = new URL(baseUrl + id, window.location.origin);\n if (range) u.searchParams.set(\"since\", range);\n const requestUrl = u.pathname + u.search;\n return {\n queryKey: [\"timeseries\", requestUrl],\n queryFn: () => fetcher(requestUrl),\n refetchInterval: refreshMs > 0 ? refreshMs : false,\n staleTime: 0,\n retry: 0,\n };\n }),\n });\n\n const rawValue = latestValue(results[0]?.data);\n const hasValue = rawValue !== undefined;\n const usage = value.transform ? value.transform(rawValue ?? 0) : (rawValue ?? 0);\n\n let limit: number | undefined;\n if (typeof max === \"number\") {\n limit = max;\n } else if (maxSeries) {\n const rawMax = latestValue(results[1]?.data);\n limit = rawMax === undefined ? undefined : maxSeries.transform ? maxSeries.transform(rawMax) : rawMax;\n }\n\n const bounded = hasValue && limit !== undefined && limit > 0;\n const pct = bounded ? Math.min(100, Math.round((usage / (limit as number)) * 100)) : 0;\n const tone = toneClass(pct, thresholds);\n const toneBg = toneBgClass(pct, thresholds);\n const readout =\n centerDisplay === \"percent\"\n ? bounded\n ? `${pct}%`\n : hasValue\n ? \"n/a\"\n : \"—\"\n : hasValue\n ? formatUnit(usage, unit)\n : \"—\";\n const titleText = `${title}: ${readout}`;\n const canExpand = expandable && variant === \"default\";\n const readoutTone = bounded ? tone : \"text-foreground\";\n\n const chartSeries: TimeseriesSeries[] = useMemo(() => {\n const s: TimeseriesSeries[] = [{ id: value.id, label: \"value\", ...(value.transform ? { transform: value.transform } : {}) }];\n if (maxSeries) s.push({ id: maxSeries.id, label: \"max\", ...(maxSeries.transform ? { transform: maxSeries.transform } : {}) });\n return s;\n }, [value.id, value.transform, maxSeries]);\n\n // Hover card: reduce the value's points to current/min/max/avg (transformed to\n // the display unit), plus the resolved capacity. The current row is tinted by\n // its threshold tone when the reading is bounded.\n const stats = seriesStats(results[0]?.data?.points, value.transform);\n const fmt = (n: number) => formatUnit(n, unit);\n const hoverRows: GaugeHoverRow[] = hasValue\n ? [\n { label: \"Current\", value: fmt(usage), ...(bounded ? { tone } : {}) },\n ...(stats\n ? [\n { label: \"Min\", value: fmt(stats.min) },\n { label: \"Max\", value: fmt(stats.max) },\n { label: \"Avg\", value: fmt(stats.avg) },\n ]\n : []),\n ...(limit !== undefined\n ? [{ label: \"Capacity\", value: fmt(limit) }]\n : []),\n ]\n : [];\n const useHover = hoverCard && hoverRows.length > 0;\n const footer = `over last ${range}`;\n\n if (variant === \"cell\") {\n const cell = (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs\",\n className,\n )}\n {...(useHover ? {} : { title: titleText })}\n aria-label={useHover || !showLabel ? titleText : undefined}\n data-shape={shape}\n >\n {icon ? <GaugeIcon icon={icon} /> : null}\n {showLabel ? <span className=\"min-w-0 truncate text-muted-foreground\">{title}</span> : null}\n {shape === \"linear\" ? (\n <GaugeBar pct={pct} toneBg={toneBg} className=\"h-1.5 w-12 shrink-0\" />\n ) : (\n <span className=\"relative h-4 w-8 shrink-0\" aria-hidden=\"true\">\n <GaugeArc pct={pct} tone={tone} strokeWidth={10} />\n </span>\n )}\n <span className={cn(\"shrink-0 font-semibold tabular-nums\", readoutTone)}>\n {readout}\n </span>\n </span>\n );\n return useHover ? (\n <GaugeHoverCard title={title} rows={hoverRows} footer={footer} trigger={cell} />\n ) : (\n cell\n );\n }\n\n const body = (\n <div\n className={cn(\"flex flex-col items-center gap-1\", className)}\n {...(useHover ? {} : { title: !showLabel ? titleText : undefined })}\n aria-label={useHover || !showLabel ? titleText : undefined}\n data-shape={shape}\n >\n {shape === \"linear\" ? (\n <div className=\"flex w-full items-center gap-2\">\n <GaugeBar pct={pct} toneBg={toneBg} className=\"h-2 w-full\" />\n <span className=\"shrink-0 text-sm font-semibold text-foreground\">{readout}</span>\n {canExpand && (\n <button\n type=\"button\"\n aria-label=\"Expand chart\"\n onClick={() => setExpanded(true)}\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={UiFullscreen} width={12} height={12} />\n </button>\n )}\n </div>\n ) : (\n <div className=\"relative h-10 w-20\">\n <GaugeArc pct={pct} tone={tone} strokeWidth={9} />\n <span className=\"absolute inset-x-0 bottom-0 text-center text-sm font-semibold text-foreground\">\n {readout}\n </span>\n {canExpand && (\n <button\n type=\"button\"\n aria-label=\"Expand chart\"\n onClick={() => setExpanded(true)}\n className=\"absolute right-0 top-0 text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={UiFullscreen} width={12} height={12} />\n </button>\n )}\n </div>\n )}\n {icon || showLabel ? (\n <div className=\"flex items-center gap-1 text-xs text-muted-foreground\">\n {icon ? <GaugeIcon icon={icon} /> : null}\n {showLabel ? <span>{title}</span> : null}\n </div>\n ) : null}\n </div>\n );\n\n return (\n <>\n {useHover ? (\n <GaugeHoverCard\n title={title}\n rows={hoverRows}\n footer={footer}\n trigger={body}\n className=\"w-full justify-center\"\n />\n ) : (\n body\n )}\n {canExpand && (\n <Modal open={expanded} onClose={() => setExpanded(false)} title={title} size=\"xl\">\n <TimeseriesPanel\n title={title}\n {...(icon ? { icon } : {})}\n {...(unit ? { unit } : {})}\n baseUrl={baseUrl}\n series={chartSeries}\n range={range}\n refreshMs={refreshMs}\n expandable={false}\n fetcher={fetcher}\n />\n </Modal>\n )}\n </>\n );\n}\n"],"names":["jsxs","jsx","cn","Icon","useState","useMemo","useQueries","formatUnit","seriesStats","GaugeHoverCard","UiFullscreen","Fragment","Modal","TimeseriesPanel"],"mappings":"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"}
@@ -8,6 +8,8 @@ export interface GaugeSeries {
8
8
  transform?: (value: number) => number;
9
9
  }
10
10
  export type TimeseriesGaugeVariant = "default" | "cell";
11
+ /** Gauge fill geometry: a half-circle arc (default) or a horizontal progress bar. */
12
+ export type TimeseriesGaugeShape = "radial" | "linear";
11
13
  export interface TimeseriesGaugeProps {
12
14
  /** Common prefix; the value/max requests are `baseUrl + id`. */
13
15
  baseUrl?: string;
@@ -42,8 +44,15 @@ export interface TimeseriesGaugeProps {
42
44
  centerDisplay?: "value" | "percent";
43
45
  /** Visual density/layout. `cell` is a compact inline form for table/grid cells. */
44
46
  variant?: TimeseriesGaugeVariant;
47
+ /** Fill geometry: a radial half-gauge (default) or a horizontal progress bar. */
48
+ shape?: TimeseriesGaugeShape;
45
49
  /** Show the title text. Icons and values remain visible when false. */
46
50
  showLabel?: boolean;
51
+ /**
52
+ * Wrap the gauge in a hover card summarising the metric (label + current / min /
53
+ * max / avg / capacity over the window). Defaults to true.
54
+ */
55
+ hoverCard?: boolean;
47
56
  /** Override the default fetch (e.g. to route through an app's API client). */
48
57
  fetcher?: (url: string) => Promise<TimeseriesResponse>;
49
58
  className?: string;
@@ -57,5 +66,5 @@ export interface TimeseriesGaugeProps {
57
66
  * chart in a modal (a `TimeseriesPanel`), so the gauge gives the at-a-glance
58
67
  * reading and the chart the trend.
59
68
  */
60
- export declare function TimeseriesGauge({ baseUrl, value, max, title, icon, unit, range, refreshMs, expandable, thresholds, centerDisplay, variant, showLabel, fetcher, className, }: TimeseriesGaugeProps): import("react/jsx-runtime").JSX.Element;
69
+ export declare function TimeseriesGauge({ baseUrl, value, max, title, icon, unit, range, refreshMs, expandable, thresholds, centerDisplay, variant, shape, showLabel, hoverCard, fetcher, className, }: TimeseriesGaugeProps): import("react/jsx-runtime").JSX.Element;
61
70
  //# sourceMappingURL=TimeseriesGauge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimeseriesGauge.d.ts","sourceRoot":"","sources":["../../src/data/TimeseriesGauge.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,mBAAmB,CAAC;AAE3B,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,EAAE,EAAE,MAAM,CAAC;IACX,uFAAuF;IACvF,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AAED,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,KAAK,EAAE,WAAW,CAAC;IACnB;;;;OAIG;IACH,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iGAAiG;IACjG,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,mFAAmF;IACnF,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiCD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAC9B,OAAY,EACZ,KAAK,EACL,GAAG,EACH,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAY,EACZ,SAAgB,EAChB,UAAiB,EACjB,UAAqB,EACrB,aAAuB,EACvB,OAAmB,EACnB,SAAgB,EAChB,OAAwB,EACxB,SAAS,GACV,EAAE,oBAAoB,2CAgKtB"}
1
+ {"version":3,"file":"TimeseriesGauge.d.ts","sourceRoot":"","sources":["../../src/data/TimeseriesGauge.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,mBAAmB,CAAC;AAI3B,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,EAAE,EAAE,MAAM,CAAC;IACX,uFAAuF;IACvF,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACvC;AAED,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,MAAM,CAAC;AACxD,qFAAqF;AACrF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,KAAK,EAAE,WAAW,CAAC;IACnB;;;;OAIG;IACH,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iGAAiG;IACjG,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,mFAAmF;IACnF,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,iFAAiF;IACjF,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0ED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAC9B,OAAY,EACZ,KAAK,EACL,GAAG,EACH,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAY,EACZ,SAAgB,EAChB,UAAiB,EACjB,UAAqB,EACrB,aAAuB,EACvB,OAAmB,EACnB,KAAgB,EAChB,SAAgB,EAChB,SAAgB,EAChB,OAAwB,EACxB,SAAS,GACV,EAAE,oBAAoB,2CAoMtB"}