@burdenoff/microfe-assethandler 2026.826.3 → 2026.826.4

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 (565) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +1 -1
  2. package/dist/assethandler/AssetHandlerRoot.js.map +1 -1
  3. package/dist/assethandler/AssetHandlerRoutes.js.map +1 -1
  4. package/dist/assethandler/components/ActivityTimeline.js.map +1 -1
  5. package/dist/assethandler/components/AttachmentsPanel.js.map +1 -1
  6. package/dist/assethandler/components/ChartCard.js.map +1 -1
  7. package/dist/assethandler/components/CommentsPanel.js.map +1 -1
  8. package/dist/assethandler/components/NotFoundState.js.map +1 -1
  9. package/dist/assethandler/components/Pagination.js.map +1 -1
  10. package/dist/assethandler/components/SectionHeader.js.map +1 -1
  11. package/dist/assethandler/components/StatTile.js.map +1 -1
  12. package/dist/assethandler/components/charts/BarsChart.js.map +1 -1
  13. package/dist/assethandler/components/charts/ChartParts.js.map +1 -1
  14. package/dist/assethandler/components/charts/DonutChart.js.map +1 -1
  15. package/dist/assethandler/components/charts/ProgressMeter.js.map +1 -1
  16. package/dist/assethandler/components/charts/RadialGauge.js.map +1 -1
  17. package/dist/assethandler/components/charts/Sparkline.js.map +1 -1
  18. package/dist/assethandler/components/charts/TrendChart.js.map +1 -1
  19. package/dist/assethandler/components/charts/chartTheme.js.map +1 -1
  20. package/dist/assethandler/hooks/useAssetHandlerNavigate.js.map +1 -1
  21. package/dist/assethandler/hooks/useCopy.js.map +1 -1
  22. package/dist/assethandler/hooks/useMaintenancePlans.js.map +1 -1
  23. package/dist/assethandler/ops/MaintenancePlanDialog.js.map +1 -1
  24. package/dist/assethandler/ops/NewWorkOrderDialog.js.map +1 -1
  25. package/dist/assethandler/ops/ScheduleMaintenanceDialog.js.map +1 -1
  26. package/dist/assethandler/pages/AiPredictionsPage.js.map +1 -1
  27. package/dist/assethandler/pages/AnalyticsPage.js.map +1 -1
  28. package/dist/assethandler/pages/AssetsAssetCategoriesPage.js.map +1 -1
  29. package/dist/assethandler/pages/AssetsAssetCheckInOutPage.js.map +1 -1
  30. package/dist/assethandler/pages/AssetsAssetCreatePage.js.map +1 -1
  31. package/dist/assethandler/pages/AssetsAssetDetailPage.js.map +1 -1
  32. package/dist/assethandler/pages/AssetsAssetListPage.js.map +1 -1
  33. package/dist/assethandler/pages/AssetsAssetTrackingPage.js.map +1 -1
  34. package/dist/assethandler/pages/CmdbBrowserPage.js.map +1 -1
  35. package/dist/assethandler/pages/DashboardPage.js.map +1 -1
  36. package/dist/assethandler/pages/DigitalTwinPage.js.map +1 -1
  37. package/dist/assethandler/pages/DiscoveryJobsPage.js.map +1 -1
  38. package/dist/assethandler/pages/EsgDashboardPage.js.map +1 -1
  39. package/dist/assethandler/pages/FinanceBudgetDetailPage.js.map +1 -1
  40. package/dist/assethandler/pages/FinanceFinanceHubPage.js.map +1 -1
  41. package/dist/assethandler/pages/FinanceInvoiceDetailPage.js.map +1 -1
  42. package/dist/assethandler/pages/IotDevicesPage.js.map +1 -1
  43. package/dist/assethandler/pages/ItilChangeDetailPage.js.map +1 -1
  44. package/dist/assethandler/pages/ItilChangeManagementPage.js.map +1 -1
  45. package/dist/assethandler/pages/ItilDialogs.js.map +1 -1
  46. package/dist/assethandler/pages/ItilIncidentDetailPage.js.map +1 -1
  47. package/dist/assethandler/pages/ItilIncidentManagementPage.js.map +1 -1
  48. package/dist/assethandler/pages/ItilItilhubPage.js.map +1 -1
  49. package/dist/assethandler/pages/ItilProblemDetailPage.js.map +1 -1
  50. package/dist/assethandler/pages/ItilProblemManagementPage.js.map +1 -1
  51. package/dist/assethandler/pages/KnowledgeBasePage.js.map +1 -1
  52. package/dist/assethandler/pages/MaintenanceMaintenanceCalendarPage.js.map +1 -1
  53. package/dist/assethandler/pages/MaintenanceMaintenancePlansPage.js.map +1 -1
  54. package/dist/assethandler/pages/MaintenanceMaintenanceSchedulerPage.js.map +1 -1
  55. package/dist/assethandler/pages/OperationsMaintenanceDetailPage.js.map +1 -1
  56. package/dist/assethandler/pages/OperationsOperationsHubPage.js.map +1 -1
  57. package/dist/assethandler/pages/OperationsWorkOrderDetailPage.js.map +1 -1
  58. package/dist/assethandler/pages/PortfolioPortfolioOverviewPage.js.map +1 -1
  59. package/dist/assethandler/pages/ProvenancePage.js.map +1 -1
  60. package/dist/assethandler/pages/ReportsDashboardPage.js.map +1 -1
  61. package/dist/assethandler/pages/SamLicensesPage.js.map +1 -1
  62. package/dist/assethandler/pages/SecurityComplianceDetailPage.js.map +1 -1
  63. package/dist/assethandler/pages/SecurityPolicyDetailPage.js.map +1 -1
  64. package/dist/assethandler/pages/SecuritySecurityEventDetailPage.js.map +1 -1
  65. package/dist/assethandler/pages/SecuritySecurityHubPage.js.map +1 -1
  66. package/dist/assethandler/pages/TransactionsTransactionDetailPage.js.map +1 -1
  67. package/dist/assethandler/pages/TransactionsTransactionListPage.js.map +1 -1
  68. package/dist/assethandler/providers/AssetHandlerProvider.js.map +1 -1
  69. package/dist/assethandler/store/assethandlerStore.js.map +1 -1
  70. package/dist/assethandler/utils/categoryPresentation.js.map +1 -1
  71. package/dist/assethandler/utils/cn.js.map +1 -1
  72. package/dist/assethandler/utils/csv.js.map +1 -1
  73. package/dist/assethandler/utils/i18n.js.map +1 -1
  74. package/dist/assethandler/utils/knowledgeBase.js.map +1 -1
  75. package/dist/assethandler/utils/meter.js.map +1 -1
  76. package/dist/assethandler/utils/money.js.map +1 -1
  77. package/dist/assethandler/utils/navigation.js.map +1 -1
  78. package/dist/assethandler/utils/printAssetTag.js.map +1 -1
  79. package/dist/assethandler/utils/toast.js.map +1 -1
  80. package/dist/node_modules/clsx/dist/clsx.js.map +1 -1
  81. package/dist/node_modules/d3-array/src/ascending.js.map +1 -1
  82. package/dist/node_modules/d3-array/src/bisect.js.map +1 -1
  83. package/dist/node_modules/d3-array/src/bisector.js.map +1 -1
  84. package/dist/node_modules/d3-array/src/descending.js.map +1 -1
  85. package/dist/node_modules/d3-array/src/max.js.map +1 -1
  86. package/dist/node_modules/d3-array/src/min.js.map +1 -1
  87. package/dist/node_modules/d3-array/src/number.js.map +1 -1
  88. package/dist/node_modules/d3-array/src/quantile.js.map +1 -1
  89. package/dist/node_modules/d3-array/src/quickselect.js.map +1 -1
  90. package/dist/node_modules/d3-array/src/range.js.map +1 -1
  91. package/dist/node_modules/d3-array/src/sort.js.map +1 -1
  92. package/dist/node_modules/d3-array/src/ticks.js.map +1 -1
  93. package/dist/node_modules/d3-color/src/color.js.map +1 -1
  94. package/dist/node_modules/d3-color/src/define.js.map +1 -1
  95. package/dist/node_modules/d3-format/src/defaultLocale.js.map +1 -1
  96. package/dist/node_modules/d3-format/src/exponent.js.map +1 -1
  97. package/dist/node_modules/d3-format/src/formatDecimal.js.map +1 -1
  98. package/dist/node_modules/d3-format/src/formatGroup.js.map +1 -1
  99. package/dist/node_modules/d3-format/src/formatNumerals.js.map +1 -1
  100. package/dist/node_modules/d3-format/src/formatPrefixAuto.js.map +1 -1
  101. package/dist/node_modules/d3-format/src/formatRounded.js.map +1 -1
  102. package/dist/node_modules/d3-format/src/formatSpecifier.js.map +1 -1
  103. package/dist/node_modules/d3-format/src/formatTrim.js.map +1 -1
  104. package/dist/node_modules/d3-format/src/formatTypes.js.map +1 -1
  105. package/dist/node_modules/d3-format/src/identity.js.map +1 -1
  106. package/dist/node_modules/d3-format/src/locale.js.map +1 -1
  107. package/dist/node_modules/d3-format/src/precisionFixed.js.map +1 -1
  108. package/dist/node_modules/d3-format/src/precisionPrefix.js.map +1 -1
  109. package/dist/node_modules/d3-format/src/precisionRound.js.map +1 -1
  110. package/dist/node_modules/d3-interpolate/src/array.js.map +1 -1
  111. package/dist/node_modules/d3-interpolate/src/basis.js.map +1 -1
  112. package/dist/node_modules/d3-interpolate/src/basisClosed.js.map +1 -1
  113. package/dist/node_modules/d3-interpolate/src/color.js.map +1 -1
  114. package/dist/node_modules/d3-interpolate/src/date.js.map +1 -1
  115. package/dist/node_modules/d3-interpolate/src/number.js.map +1 -1
  116. package/dist/node_modules/d3-interpolate/src/numberArray.js.map +1 -1
  117. package/dist/node_modules/d3-interpolate/src/object.js.map +1 -1
  118. package/dist/node_modules/d3-interpolate/src/piecewise.js.map +1 -1
  119. package/dist/node_modules/d3-interpolate/src/rgb.js.map +1 -1
  120. package/dist/node_modules/d3-interpolate/src/round.js.map +1 -1
  121. package/dist/node_modules/d3-interpolate/src/string.js.map +1 -1
  122. package/dist/node_modules/d3-interpolate/src/value.js.map +1 -1
  123. package/dist/node_modules/d3-path/src/path.js.map +1 -1
  124. package/dist/node_modules/d3-scale/src/band.js.map +1 -1
  125. package/dist/node_modules/d3-scale/src/constant.js.map +1 -1
  126. package/dist/node_modules/d3-scale/src/continuous.js.map +1 -1
  127. package/dist/node_modules/d3-scale/src/diverging.js.map +1 -1
  128. package/dist/node_modules/d3-scale/src/identity.js.map +1 -1
  129. package/dist/node_modules/d3-scale/src/init.js.map +1 -1
  130. package/dist/node_modules/d3-scale/src/linear.js.map +1 -1
  131. package/dist/node_modules/d3-scale/src/log.js.map +1 -1
  132. package/dist/node_modules/d3-scale/src/nice.js.map +1 -1
  133. package/dist/node_modules/d3-scale/src/number.js.map +1 -1
  134. package/dist/node_modules/d3-scale/src/ordinal.js.map +1 -1
  135. package/dist/node_modules/d3-scale/src/pow.js.map +1 -1
  136. package/dist/node_modules/d3-scale/src/quantile.js.map +1 -1
  137. package/dist/node_modules/d3-scale/src/quantize.js.map +1 -1
  138. package/dist/node_modules/d3-scale/src/radial.js.map +1 -1
  139. package/dist/node_modules/d3-scale/src/sequential.js.map +1 -1
  140. package/dist/node_modules/d3-scale/src/sequentialQuantile.js.map +1 -1
  141. package/dist/node_modules/d3-scale/src/symlog.js.map +1 -1
  142. package/dist/node_modules/d3-scale/src/threshold.js.map +1 -1
  143. package/dist/node_modules/d3-scale/src/tickFormat.js.map +1 -1
  144. package/dist/node_modules/d3-scale/src/time.js.map +1 -1
  145. package/dist/node_modules/d3-scale/src/utcTime.js.map +1 -1
  146. package/dist/node_modules/d3-shape/src/area.js.map +1 -1
  147. package/dist/node_modules/d3-shape/src/array.js.map +1 -1
  148. package/dist/node_modules/d3-shape/src/constant.js.map +1 -1
  149. package/dist/node_modules/d3-shape/src/curve/basis.js.map +1 -1
  150. package/dist/node_modules/d3-shape/src/curve/basisClosed.js.map +1 -1
  151. package/dist/node_modules/d3-shape/src/curve/basisOpen.js.map +1 -1
  152. package/dist/node_modules/d3-shape/src/curve/bump.js.map +1 -1
  153. package/dist/node_modules/d3-shape/src/curve/linear.js.map +1 -1
  154. package/dist/node_modules/d3-shape/src/curve/linearClosed.js.map +1 -1
  155. package/dist/node_modules/d3-shape/src/curve/monotone.js.map +1 -1
  156. package/dist/node_modules/d3-shape/src/curve/natural.js.map +1 -1
  157. package/dist/node_modules/d3-shape/src/curve/step.js.map +1 -1
  158. package/dist/node_modules/d3-shape/src/line.js.map +1 -1
  159. package/dist/node_modules/d3-shape/src/noop.js.map +1 -1
  160. package/dist/node_modules/d3-shape/src/offset/expand.js.map +1 -1
  161. package/dist/node_modules/d3-shape/src/offset/none.js.map +1 -1
  162. package/dist/node_modules/d3-shape/src/offset/silhouette.js.map +1 -1
  163. package/dist/node_modules/d3-shape/src/offset/wiggle.js.map +1 -1
  164. package/dist/node_modules/d3-shape/src/order/none.js.map +1 -1
  165. package/dist/node_modules/d3-shape/src/path.js.map +1 -1
  166. package/dist/node_modules/d3-shape/src/point.js.map +1 -1
  167. package/dist/node_modules/d3-shape/src/stack.js.map +1 -1
  168. package/dist/node_modules/d3-shape/src/symbol/circle.js.map +1 -1
  169. package/dist/node_modules/d3-shape/src/symbol/cross.js.map +1 -1
  170. package/dist/node_modules/d3-shape/src/symbol/diamond.js.map +1 -1
  171. package/dist/node_modules/d3-shape/src/symbol/square.js.map +1 -1
  172. package/dist/node_modules/d3-shape/src/symbol/star.js.map +1 -1
  173. package/dist/node_modules/d3-shape/src/symbol/triangle.js.map +1 -1
  174. package/dist/node_modules/d3-shape/src/symbol/wye.js.map +1 -1
  175. package/dist/node_modules/d3-shape/src/symbol.js.map +1 -1
  176. package/dist/node_modules/d3-time/src/day.js.map +1 -1
  177. package/dist/node_modules/d3-time/src/hour.js.map +1 -1
  178. package/dist/node_modules/d3-time/src/interval.js.map +1 -1
  179. package/dist/node_modules/d3-time/src/millisecond.js.map +1 -1
  180. package/dist/node_modules/d3-time/src/minute.js.map +1 -1
  181. package/dist/node_modules/d3-time/src/month.js.map +1 -1
  182. package/dist/node_modules/d3-time/src/second.js.map +1 -1
  183. package/dist/node_modules/d3-time/src/ticks.js.map +1 -1
  184. package/dist/node_modules/d3-time/src/week.js.map +1 -1
  185. package/dist/node_modules/d3-time/src/year.js.map +1 -1
  186. package/dist/node_modules/d3-time-format/src/defaultLocale.js.map +1 -1
  187. package/dist/node_modules/d3-time-format/src/locale.js.map +1 -1
  188. package/dist/node_modules/decimal.js-light/decimal.js.map +1 -1
  189. package/dist/node_modules/dijkstrajs/dijkstra.js.map +1 -1
  190. package/dist/node_modules/eventemitter3/index.js.map +1 -1
  191. package/dist/node_modules/fast-equals/dist/es/index.js.map +1 -1
  192. package/dist/node_modules/internmap/src/index.js.map +1 -1
  193. package/dist/node_modules/lodash/_DataView.js.map +1 -1
  194. package/dist/node_modules/lodash/_Hash.js.map +1 -1
  195. package/dist/node_modules/lodash/_ListCache.js.map +1 -1
  196. package/dist/node_modules/lodash/_Map.js.map +1 -1
  197. package/dist/node_modules/lodash/_MapCache.js.map +1 -1
  198. package/dist/node_modules/lodash/_Promise.js.map +1 -1
  199. package/dist/node_modules/lodash/_Set.js.map +1 -1
  200. package/dist/node_modules/lodash/_SetCache.js.map +1 -1
  201. package/dist/node_modules/lodash/_Stack.js +2 -1
  202. package/dist/node_modules/lodash/_Stack.js.map +1 -1
  203. package/dist/node_modules/lodash/_Symbol.js.map +1 -1
  204. package/dist/node_modules/lodash/_Uint8Array.js.map +1 -1
  205. package/dist/node_modules/lodash/_WeakMap.js.map +1 -1
  206. package/dist/node_modules/lodash/_apply.js.map +1 -1
  207. package/dist/node_modules/lodash/_arrayEvery.js.map +1 -1
  208. package/dist/node_modules/lodash/_arrayFilter.js.map +1 -1
  209. package/dist/node_modules/lodash/_arrayIncludes.js.map +1 -1
  210. package/dist/node_modules/lodash/_arrayIncludesWith.js.map +1 -1
  211. package/dist/node_modules/lodash/_arrayLikeKeys.js.map +1 -1
  212. package/dist/node_modules/lodash/_arrayMap.js.map +1 -1
  213. package/dist/node_modules/lodash/_arrayPush.js.map +1 -1
  214. package/dist/node_modules/lodash/_arraySome.js.map +1 -1
  215. package/dist/node_modules/lodash/_asciiToArray.js.map +1 -1
  216. package/dist/node_modules/lodash/_assocIndexOf.js.map +1 -1
  217. package/dist/node_modules/lodash/_baseAssignValue.js.map +1 -1
  218. package/dist/node_modules/lodash/_baseEach.js.map +1 -1
  219. package/dist/node_modules/lodash/_baseEvery.js.map +1 -1
  220. package/dist/node_modules/lodash/_baseExtremum.js.map +1 -1
  221. package/dist/node_modules/lodash/_baseFindIndex.js.map +1 -1
  222. package/dist/node_modules/lodash/_baseFlatten.js.map +1 -1
  223. package/dist/node_modules/lodash/_baseFor.js.map +1 -1
  224. package/dist/node_modules/lodash/_baseForOwn.js.map +1 -1
  225. package/dist/node_modules/lodash/_baseGet.js.map +1 -1
  226. package/dist/node_modules/lodash/_baseGetAllKeys.js.map +1 -1
  227. package/dist/node_modules/lodash/_baseGetTag.js.map +1 -1
  228. package/dist/node_modules/lodash/_baseGt.js.map +1 -1
  229. package/dist/node_modules/lodash/_baseHasIn.js.map +1 -1
  230. package/dist/node_modules/lodash/_baseIndexOf.js.map +1 -1
  231. package/dist/node_modules/lodash/_baseIsArguments.js.map +1 -1
  232. package/dist/node_modules/lodash/_baseIsEqual.js.map +1 -1
  233. package/dist/node_modules/lodash/_baseIsEqualDeep.js.map +1 -1
  234. package/dist/node_modules/lodash/_baseIsMatch.js.map +1 -1
  235. package/dist/node_modules/lodash/_baseIsNaN.js.map +1 -1
  236. package/dist/node_modules/lodash/_baseIsNative.js.map +1 -1
  237. package/dist/node_modules/lodash/_baseIsTypedArray.js.map +1 -1
  238. package/dist/node_modules/lodash/_baseIteratee.js.map +1 -1
  239. package/dist/node_modules/lodash/_baseKeys.js.map +1 -1
  240. package/dist/node_modules/lodash/_baseLt.js.map +1 -1
  241. package/dist/node_modules/lodash/_baseMap.js.map +1 -1
  242. package/dist/node_modules/lodash/_baseMatches.js.map +1 -1
  243. package/dist/node_modules/lodash/_baseMatchesProperty.js.map +1 -1
  244. package/dist/node_modules/lodash/_baseOrderBy.js.map +1 -1
  245. package/dist/node_modules/lodash/_baseProperty.js.map +1 -1
  246. package/dist/node_modules/lodash/_basePropertyDeep.js.map +1 -1
  247. package/dist/node_modules/lodash/_baseRange.js.map +1 -1
  248. package/dist/node_modules/lodash/_baseRest.js.map +1 -1
  249. package/dist/node_modules/lodash/_baseSetToString.js.map +1 -1
  250. package/dist/node_modules/lodash/_baseSlice.js.map +1 -1
  251. package/dist/node_modules/lodash/_baseSome.js.map +1 -1
  252. package/dist/node_modules/lodash/_baseSortBy.js.map +1 -1
  253. package/dist/node_modules/lodash/_baseTimes.js.map +1 -1
  254. package/dist/node_modules/lodash/_baseToString.js.map +1 -1
  255. package/dist/node_modules/lodash/_baseTrim.js.map +1 -1
  256. package/dist/node_modules/lodash/_baseUnary.js.map +1 -1
  257. package/dist/node_modules/lodash/_baseUniq.js.map +1 -1
  258. package/dist/node_modules/lodash/_cacheHas.js.map +1 -1
  259. package/dist/node_modules/lodash/_castPath.js.map +1 -1
  260. package/dist/node_modules/lodash/_castSlice.js.map +1 -1
  261. package/dist/node_modules/lodash/_compareAscending.js.map +1 -1
  262. package/dist/node_modules/lodash/_compareMultiple.js.map +1 -1
  263. package/dist/node_modules/lodash/_coreJsData.js.map +1 -1
  264. package/dist/node_modules/lodash/_createBaseEach.js.map +1 -1
  265. package/dist/node_modules/lodash/_createBaseFor.js.map +1 -1
  266. package/dist/node_modules/lodash/_createCaseFirst.js.map +1 -1
  267. package/dist/node_modules/lodash/_createFind.js.map +1 -1
  268. package/dist/node_modules/lodash/_createRange.js.map +1 -1
  269. package/dist/node_modules/lodash/_createSet.js.map +1 -1
  270. package/dist/node_modules/lodash/_defineProperty.js.map +1 -1
  271. package/dist/node_modules/lodash/_equalArrays.js.map +1 -1
  272. package/dist/node_modules/lodash/_equalByTag.js.map +1 -1
  273. package/dist/node_modules/lodash/_equalObjects.js.map +1 -1
  274. package/dist/node_modules/lodash/_freeGlobal.js.map +1 -1
  275. package/dist/node_modules/lodash/_getAllKeys.js.map +1 -1
  276. package/dist/node_modules/lodash/_getMapData.js.map +1 -1
  277. package/dist/node_modules/lodash/_getMatchData.js.map +1 -1
  278. package/dist/node_modules/lodash/_getNative.js.map +1 -1
  279. package/dist/node_modules/lodash/_getPrototype.js.map +1 -1
  280. package/dist/node_modules/lodash/_getRawTag.js.map +1 -1
  281. package/dist/node_modules/lodash/_getSymbols.js.map +1 -1
  282. package/dist/node_modules/lodash/_getTag.js.map +1 -1
  283. package/dist/node_modules/lodash/_getValue.js.map +1 -1
  284. package/dist/node_modules/lodash/_hasPath.js.map +1 -1
  285. package/dist/node_modules/lodash/_hasUnicode.js.map +1 -1
  286. package/dist/node_modules/lodash/_hashClear.js.map +1 -1
  287. package/dist/node_modules/lodash/_hashDelete.js.map +1 -1
  288. package/dist/node_modules/lodash/_hashGet.js.map +1 -1
  289. package/dist/node_modules/lodash/_hashHas.js.map +1 -1
  290. package/dist/node_modules/lodash/_hashSet.js.map +1 -1
  291. package/dist/node_modules/lodash/_isFlattenable.js.map +1 -1
  292. package/dist/node_modules/lodash/_isIndex.js.map +1 -1
  293. package/dist/node_modules/lodash/_isIterateeCall.js.map +1 -1
  294. package/dist/node_modules/lodash/_isKey.js.map +1 -1
  295. package/dist/node_modules/lodash/_isKeyable.js.map +1 -1
  296. package/dist/node_modules/lodash/_isMasked.js.map +1 -1
  297. package/dist/node_modules/lodash/_isPrototype.js.map +1 -1
  298. package/dist/node_modules/lodash/_isStrictComparable.js.map +1 -1
  299. package/dist/node_modules/lodash/_listCacheClear.js.map +1 -1
  300. package/dist/node_modules/lodash/_listCacheDelete.js.map +1 -1
  301. package/dist/node_modules/lodash/_listCacheGet.js.map +1 -1
  302. package/dist/node_modules/lodash/_listCacheHas.js.map +1 -1
  303. package/dist/node_modules/lodash/_listCacheSet.js.map +1 -1
  304. package/dist/node_modules/lodash/_mapCacheClear.js.map +1 -1
  305. package/dist/node_modules/lodash/_mapCacheDelete.js.map +1 -1
  306. package/dist/node_modules/lodash/_mapCacheGet.js.map +1 -1
  307. package/dist/node_modules/lodash/_mapCacheHas.js.map +1 -1
  308. package/dist/node_modules/lodash/_mapCacheSet.js.map +1 -1
  309. package/dist/node_modules/lodash/_mapToArray.js.map +1 -1
  310. package/dist/node_modules/lodash/_matchesStrictComparable.js.map +1 -1
  311. package/dist/node_modules/lodash/_memoizeCapped.js.map +1 -1
  312. package/dist/node_modules/lodash/_nativeCreate.js.map +1 -1
  313. package/dist/node_modules/lodash/_nativeKeys.js.map +1 -1
  314. package/dist/node_modules/lodash/_nodeUtil.js.map +1 -1
  315. package/dist/node_modules/lodash/_objectToString.js.map +1 -1
  316. package/dist/node_modules/lodash/_overArg.js.map +1 -1
  317. package/dist/node_modules/lodash/_overRest.js.map +1 -1
  318. package/dist/node_modules/lodash/_root.js.map +1 -1
  319. package/dist/node_modules/lodash/_setCacheAdd.js.map +1 -1
  320. package/dist/node_modules/lodash/_setCacheHas.js.map +1 -1
  321. package/dist/node_modules/lodash/_setToArray.js.map +1 -1
  322. package/dist/node_modules/lodash/_setToString.js.map +1 -1
  323. package/dist/node_modules/lodash/_shortOut.js.map +1 -1
  324. package/dist/node_modules/lodash/_stackClear.js.map +1 -1
  325. package/dist/node_modules/lodash/_stackDelete.js.map +1 -1
  326. package/dist/node_modules/lodash/_stackGet.js.map +1 -1
  327. package/dist/node_modules/lodash/_stackHas.js.map +1 -1
  328. package/dist/node_modules/lodash/_stackSet.js.map +1 -1
  329. package/dist/node_modules/lodash/_strictIndexOf.js.map +1 -1
  330. package/dist/node_modules/lodash/_stringToArray.js.map +1 -1
  331. package/dist/node_modules/lodash/_stringToPath.js.map +1 -1
  332. package/dist/node_modules/lodash/_toKey.js.map +1 -1
  333. package/dist/node_modules/lodash/_toSource.js.map +1 -1
  334. package/dist/node_modules/lodash/_trimmedEndIndex.js.map +1 -1
  335. package/dist/node_modules/lodash/_unicodeToArray.js.map +1 -1
  336. package/dist/node_modules/lodash/constant.js.map +1 -1
  337. package/dist/node_modules/lodash/debounce.js.map +1 -1
  338. package/dist/node_modules/lodash/eq.js.map +1 -1
  339. package/dist/node_modules/lodash/every.js.map +1 -1
  340. package/dist/node_modules/lodash/find.js.map +1 -1
  341. package/dist/node_modules/lodash/findIndex.js.map +1 -1
  342. package/dist/node_modules/lodash/flatMap.js.map +1 -1
  343. package/dist/node_modules/lodash/get.js.map +1 -1
  344. package/dist/node_modules/lodash/hasIn.js.map +1 -1
  345. package/dist/node_modules/lodash/identity.js.map +1 -1
  346. package/dist/node_modules/lodash/isArguments.js.map +1 -1
  347. package/dist/node_modules/lodash/isArray.js.map +1 -1
  348. package/dist/node_modules/lodash/isArrayLike.js.map +1 -1
  349. package/dist/node_modules/lodash/isBoolean.js.map +1 -1
  350. package/dist/node_modules/lodash/isBuffer.js.map +1 -1
  351. package/dist/node_modules/lodash/isEqual.js.map +1 -1
  352. package/dist/node_modules/lodash/isFunction.js.map +1 -1
  353. package/dist/node_modules/lodash/isLength.js.map +1 -1
  354. package/dist/node_modules/lodash/isNaN.js.map +1 -1
  355. package/dist/node_modules/lodash/isNil.js.map +1 -1
  356. package/dist/node_modules/lodash/isNumber.js.map +1 -1
  357. package/dist/node_modules/lodash/isObject.js.map +1 -1
  358. package/dist/node_modules/lodash/isObjectLike.js.map +1 -1
  359. package/dist/node_modules/lodash/isPlainObject.js.map +1 -1
  360. package/dist/node_modules/lodash/isString.js.map +1 -1
  361. package/dist/node_modules/lodash/isSymbol.js.map +1 -1
  362. package/dist/node_modules/lodash/isTypedArray.js.map +1 -1
  363. package/dist/node_modules/lodash/keys.js.map +1 -1
  364. package/dist/node_modules/lodash/last.js.map +1 -1
  365. package/dist/node_modules/lodash/map.js.map +1 -1
  366. package/dist/node_modules/lodash/mapValues.js.map +1 -1
  367. package/dist/node_modules/lodash/max.js.map +1 -1
  368. package/dist/node_modules/lodash/maxBy.js.map +1 -1
  369. package/dist/node_modules/lodash/memoize.js.map +1 -1
  370. package/dist/node_modules/lodash/min.js.map +1 -1
  371. package/dist/node_modules/lodash/minBy.js.map +1 -1
  372. package/dist/node_modules/lodash/noop.js.map +1 -1
  373. package/dist/node_modules/lodash/now.js.map +1 -1
  374. package/dist/node_modules/lodash/property.js.map +1 -1
  375. package/dist/node_modules/lodash/range.js.map +1 -1
  376. package/dist/node_modules/lodash/some.js.map +1 -1
  377. package/dist/node_modules/lodash/sortBy.js.map +1 -1
  378. package/dist/node_modules/lodash/stubArray.js.map +1 -1
  379. package/dist/node_modules/lodash/stubFalse.js.map +1 -1
  380. package/dist/node_modules/lodash/throttle.js.map +1 -1
  381. package/dist/node_modules/lodash/toFinite.js.map +1 -1
  382. package/dist/node_modules/lodash/toInteger.js.map +1 -1
  383. package/dist/node_modules/lodash/toNumber.js.map +1 -1
  384. package/dist/node_modules/lodash/toString.js.map +1 -1
  385. package/dist/node_modules/lodash/uniqBy.js.map +1 -1
  386. package/dist/node_modules/lodash/upperFirst.js.map +1 -1
  387. package/dist/node_modules/object-assign/index.js.map +1 -1
  388. package/dist/node_modules/prop-types/checkPropTypes.js.map +1 -1
  389. package/dist/node_modules/prop-types/factoryWithThrowingShims.js.map +1 -1
  390. package/dist/node_modules/prop-types/factoryWithTypeCheckers.js.map +1 -1
  391. package/dist/node_modules/prop-types/index.js.map +1 -1
  392. package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js.map +1 -1
  393. package/dist/node_modules/prop-types/lib/has.js.map +1 -1
  394. package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.development.js.map +1 -1
  395. package/dist/node_modules/prop-types/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
  396. package/dist/node_modules/prop-types/node_modules/react-is/index.js.map +1 -1
  397. package/dist/node_modules/qrcode/lib/browser.js.map +1 -1
  398. package/dist/node_modules/qrcode/lib/can-promise.js.map +1 -1
  399. package/dist/node_modules/qrcode/lib/core/alignment-pattern.js.map +1 -1
  400. package/dist/node_modules/qrcode/lib/core/alphanumeric-data.js.map +1 -1
  401. package/dist/node_modules/qrcode/lib/core/bit-buffer.js.map +1 -1
  402. package/dist/node_modules/qrcode/lib/core/bit-matrix.js.map +1 -1
  403. package/dist/node_modules/qrcode/lib/core/byte-data.js.map +1 -1
  404. package/dist/node_modules/qrcode/lib/core/error-correction-code.js.map +1 -1
  405. package/dist/node_modules/qrcode/lib/core/error-correction-level.js.map +1 -1
  406. package/dist/node_modules/qrcode/lib/core/finder-pattern.js.map +1 -1
  407. package/dist/node_modules/qrcode/lib/core/format-info.js.map +1 -1
  408. package/dist/node_modules/qrcode/lib/core/galois-field.js.map +1 -1
  409. package/dist/node_modules/qrcode/lib/core/kanji-data.js.map +1 -1
  410. package/dist/node_modules/qrcode/lib/core/mask-pattern.js.map +1 -1
  411. package/dist/node_modules/qrcode/lib/core/mode.js.map +1 -1
  412. package/dist/node_modules/qrcode/lib/core/numeric-data.js.map +1 -1
  413. package/dist/node_modules/qrcode/lib/core/polynomial.js.map +1 -1
  414. package/dist/node_modules/qrcode/lib/core/qrcode.js.map +1 -1
  415. package/dist/node_modules/qrcode/lib/core/reed-solomon-encoder.js.map +1 -1
  416. package/dist/node_modules/qrcode/lib/core/regex.js +1 -1
  417. package/dist/node_modules/qrcode/lib/core/regex.js.map +1 -1
  418. package/dist/node_modules/qrcode/lib/core/segments.js.map +1 -1
  419. package/dist/node_modules/qrcode/lib/core/utils.js.map +1 -1
  420. package/dist/node_modules/qrcode/lib/core/version-check.js.map +1 -1
  421. package/dist/node_modules/qrcode/lib/core/version.js.map +1 -1
  422. package/dist/node_modules/qrcode/lib/renderer/canvas.js.map +1 -1
  423. package/dist/node_modules/qrcode/lib/renderer/svg-tag.js.map +1 -1
  424. package/dist/node_modules/qrcode/lib/renderer/utils.js.map +1 -1
  425. package/dist/node_modules/react-is/cjs/react-is.development.js.map +1 -1
  426. package/dist/node_modules/react-is/cjs/react-is.production.min.js.map +1 -1
  427. package/dist/node_modules/react-is/index.js.map +1 -1
  428. package/dist/node_modules/react-smooth/es6/Animate.js +2 -2
  429. package/dist/node_modules/react-smooth/es6/Animate.js.map +1 -1
  430. package/dist/node_modules/react-smooth/es6/AnimateManager.js.map +1 -1
  431. package/dist/node_modules/react-smooth/es6/configUpdate.js.map +1 -1
  432. package/dist/node_modules/react-smooth/es6/easing.js.map +1 -1
  433. package/dist/node_modules/react-smooth/es6/setRafTimeout.js.map +1 -1
  434. package/dist/node_modules/react-smooth/es6/util.js.map +1 -1
  435. package/dist/node_modules/recharts/es6/cartesian/Area.js +13 -13
  436. package/dist/node_modules/recharts/es6/cartesian/Area.js.map +1 -1
  437. package/dist/node_modules/recharts/es6/cartesian/Bar.js +9 -9
  438. package/dist/node_modules/recharts/es6/cartesian/Bar.js.map +1 -1
  439. package/dist/node_modules/recharts/es6/cartesian/Brush.js +12 -12
  440. package/dist/node_modules/recharts/es6/cartesian/Brush.js.map +1 -1
  441. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js +7 -7
  442. package/dist/node_modules/recharts/es6/cartesian/CartesianAxis.js.map +1 -1
  443. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js +13 -13
  444. package/dist/node_modules/recharts/es6/cartesian/CartesianGrid.js.map +1 -1
  445. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js +4 -4
  446. package/dist/node_modules/recharts/es6/cartesian/ErrorBar.js.map +1 -1
  447. package/dist/node_modules/recharts/es6/cartesian/Line.js +10 -10
  448. package/dist/node_modules/recharts/es6/cartesian/Line.js.map +1 -1
  449. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js +3 -3
  450. package/dist/node_modules/recharts/es6/cartesian/ReferenceArea.js.map +1 -1
  451. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js +3 -3
  452. package/dist/node_modules/recharts/es6/cartesian/ReferenceDot.js.map +1 -1
  453. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js +4 -4
  454. package/dist/node_modules/recharts/es6/cartesian/ReferenceLine.js.map +1 -1
  455. package/dist/node_modules/recharts/es6/cartesian/XAxis.js +3 -3
  456. package/dist/node_modules/recharts/es6/cartesian/XAxis.js.map +1 -1
  457. package/dist/node_modules/recharts/es6/cartesian/YAxis.js +3 -3
  458. package/dist/node_modules/recharts/es6/cartesian/YAxis.js.map +1 -1
  459. package/dist/node_modules/recharts/es6/cartesian/getEquidistantTicks.js.map +1 -1
  460. package/dist/node_modules/recharts/es6/cartesian/getTicks.js.map +1 -1
  461. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js +1 -1
  462. package/dist/node_modules/recharts/es6/chart/AccessibilityManager.js.map +1 -1
  463. package/dist/node_modules/recharts/es6/chart/AreaChart.js.map +1 -1
  464. package/dist/node_modules/recharts/es6/chart/BarChart.js.map +1 -1
  465. package/dist/node_modules/recharts/es6/chart/LineChart.js.map +1 -1
  466. package/dist/node_modules/recharts/es6/chart/PieChart.js.map +1 -1
  467. package/dist/node_modules/recharts/es6/chart/RadialBarChart.js.map +1 -1
  468. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js +22 -22
  469. package/dist/node_modules/recharts/es6/chart/generateCategoricalChart.js.map +1 -1
  470. package/dist/node_modules/recharts/es6/component/Cell.js.map +1 -1
  471. package/dist/node_modules/recharts/es6/component/Cursor.js +1 -1
  472. package/dist/node_modules/recharts/es6/component/Cursor.js.map +1 -1
  473. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js +11 -11
  474. package/dist/node_modules/recharts/es6/component/DefaultLegendContent.js.map +1 -1
  475. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js +6 -6
  476. package/dist/node_modules/recharts/es6/component/DefaultTooltipContent.js.map +1 -1
  477. package/dist/node_modules/recharts/es6/component/Label.js +14 -14
  478. package/dist/node_modules/recharts/es6/component/Label.js.map +1 -1
  479. package/dist/node_modules/recharts/es6/component/LabelList.js +6 -6
  480. package/dist/node_modules/recharts/es6/component/LabelList.js.map +1 -1
  481. package/dist/node_modules/recharts/es6/component/Legend.js +5 -5
  482. package/dist/node_modules/recharts/es6/component/Legend.js.map +1 -1
  483. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js +3 -3
  484. package/dist/node_modules/recharts/es6/component/ResponsiveContainer.js.map +1 -1
  485. package/dist/node_modules/recharts/es6/component/Text.js +2 -2
  486. package/dist/node_modules/recharts/es6/component/Text.js.map +1 -1
  487. package/dist/node_modules/recharts/es6/component/Tooltip.js +3 -3
  488. package/dist/node_modules/recharts/es6/component/Tooltip.js.map +1 -1
  489. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js +2 -2
  490. package/dist/node_modules/recharts/es6/component/TooltipBoundingBox.js.map +1 -1
  491. package/dist/node_modules/recharts/es6/container/Layer.js +2 -2
  492. package/dist/node_modules/recharts/es6/container/Layer.js.map +1 -1
  493. package/dist/node_modules/recharts/es6/container/Surface.js +2 -2
  494. package/dist/node_modules/recharts/es6/container/Surface.js.map +1 -1
  495. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js +2 -2
  496. package/dist/node_modules/recharts/es6/context/chartLayoutContext.js.map +1 -1
  497. package/dist/node_modules/recharts/es6/polar/Pie.js +13 -13
  498. package/dist/node_modules/recharts/es6/polar/Pie.js.map +1 -1
  499. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js +8 -8
  500. package/dist/node_modules/recharts/es6/polar/PolarAngleAxis.js.map +1 -1
  501. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js +6 -6
  502. package/dist/node_modules/recharts/es6/polar/PolarRadiusAxis.js.map +1 -1
  503. package/dist/node_modules/recharts/es6/polar/RadialBar.js +6 -6
  504. package/dist/node_modules/recharts/es6/polar/RadialBar.js.map +1 -1
  505. package/dist/node_modules/recharts/es6/shape/Cross.js +1 -1
  506. package/dist/node_modules/recharts/es6/shape/Cross.js.map +1 -1
  507. package/dist/node_modules/recharts/es6/shape/Curve.js +1 -1
  508. package/dist/node_modules/recharts/es6/shape/Curve.js.map +1 -1
  509. package/dist/node_modules/recharts/es6/shape/Dot.js +1 -1
  510. package/dist/node_modules/recharts/es6/shape/Dot.js.map +1 -1
  511. package/dist/node_modules/recharts/es6/shape/Polygon.js +4 -4
  512. package/dist/node_modules/recharts/es6/shape/Polygon.js.map +1 -1
  513. package/dist/node_modules/recharts/es6/shape/Rectangle.js +4 -4
  514. package/dist/node_modules/recharts/es6/shape/Rectangle.js.map +1 -1
  515. package/dist/node_modules/recharts/es6/shape/Sector.js +1 -1
  516. package/dist/node_modules/recharts/es6/shape/Sector.js.map +1 -1
  517. package/dist/node_modules/recharts/es6/shape/Symbols.js +1 -1
  518. package/dist/node_modules/recharts/es6/shape/Symbols.js.map +1 -1
  519. package/dist/node_modules/recharts/es6/shape/Trapezoid.js +4 -4
  520. package/dist/node_modules/recharts/es6/shape/Trapezoid.js.map +1 -1
  521. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js +9 -9
  522. package/dist/node_modules/recharts/es6/util/ActiveShapeUtils.js.map +1 -1
  523. package/dist/node_modules/recharts/es6/util/BarUtils.js +1 -1
  524. package/dist/node_modules/recharts/es6/util/BarUtils.js.map +1 -1
  525. package/dist/node_modules/recharts/es6/util/CartesianUtils.js +1 -1
  526. package/dist/node_modules/recharts/es6/util/CartesianUtils.js.map +1 -1
  527. package/dist/node_modules/recharts/es6/util/ChartUtils.js.map +1 -1
  528. package/dist/node_modules/recharts/es6/util/CssPrefixUtils.js.map +1 -1
  529. package/dist/node_modules/recharts/es6/util/DOMUtils.js.map +1 -1
  530. package/dist/node_modules/recharts/es6/util/DataUtils.js.map +1 -1
  531. package/dist/node_modules/recharts/es6/util/DetectReferenceElementsDomain.js.map +1 -1
  532. package/dist/node_modules/recharts/es6/util/Events.js.map +1 -1
  533. package/dist/node_modules/recharts/es6/util/Global.js.map +1 -1
  534. package/dist/node_modules/recharts/es6/util/IfOverflowMatches.js.map +1 -1
  535. package/dist/node_modules/recharts/es6/util/LogUtils.js.map +1 -1
  536. package/dist/node_modules/recharts/es6/util/PolarUtils.js +1 -1
  537. package/dist/node_modules/recharts/es6/util/PolarUtils.js.map +1 -1
  538. package/dist/node_modules/recharts/es6/util/RadialBarUtils.js +1 -1
  539. package/dist/node_modules/recharts/es6/util/RadialBarUtils.js.map +1 -1
  540. package/dist/node_modules/recharts/es6/util/ReactUtils.js +1 -1
  541. package/dist/node_modules/recharts/es6/util/ReactUtils.js.map +1 -1
  542. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js +1 -1
  543. package/dist/node_modules/recharts/es6/util/ReduceCSSCalc.js.map +1 -1
  544. package/dist/node_modules/recharts/es6/util/ShallowEqual.js.map +1 -1
  545. package/dist/node_modules/recharts/es6/util/TickUtils.js.map +1 -1
  546. package/dist/node_modules/recharts/es6/util/calculateViewBox.js.map +1 -1
  547. package/dist/node_modules/recharts/es6/util/cursor/getCursorPoints.js.map +1 -1
  548. package/dist/node_modules/recharts/es6/util/cursor/getCursorRectangle.js.map +1 -1
  549. package/dist/node_modules/recharts/es6/util/cursor/getRadialCursorPoints.js.map +1 -1
  550. package/dist/node_modules/recharts/es6/util/getEveryNthWithCondition.js.map +1 -1
  551. package/dist/node_modules/recharts/es6/util/getLegendProps.js.map +1 -1
  552. package/dist/node_modules/recharts/es6/util/isDomainSpecifiedByUser.js.map +1 -1
  553. package/dist/node_modules/recharts/es6/util/payload/getUniqPayload.js.map +1 -1
  554. package/dist/node_modules/recharts/es6/util/tooltip/translate.js.map +1 -1
  555. package/dist/node_modules/recharts/es6/util/types.js +1 -1
  556. package/dist/node_modules/recharts/es6/util/types.js.map +1 -1
  557. package/dist/node_modules/recharts-scale/es6/getNiceTickValues.js.map +1 -1
  558. package/dist/node_modules/recharts-scale/es6/util/arithmetic.js.map +1 -1
  559. package/dist/node_modules/recharts-scale/es6/util/utils.js.map +1 -1
  560. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1 -1
  561. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -1
  562. package/dist/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +1 -1
  563. package/dist/services/createSandboxAssistantTransport.js.map +1 -1
  564. package/dist/utils/pageContext.js.map +1 -1
  565. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"StatTile.js","names":[],"sources":["../../../src/assethandler/components/StatTile.tsx"],"sourcesContent":["import type { ComponentType } from 'react';\nimport { ArrowDownRight, ArrowUpRight, Minus } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { Sparkline } from './charts';\n\ntype DeltaDirection = 'up' | 'down' | 'neutral';\ntype DeltaTone = 'positive' | 'negative' | 'neutral';\n\nexport interface StatTileProps {\n /** Metric name, sentence case, no trailing colon. */\n label: string;\n /** The headline figure. Numbers are formatted (default `toLocaleString`). */\n value: string | number;\n /** Formats a numeric `value` (e.g. compact / currency). */\n format?: (value: number) => string;\n /** Optional change pill text, e.g. `\"+12%\"` or `\"3 more\"`. */\n delta?: string | number;\n /** Arrow direction of the change. */\n deltaDirection?: DeltaDirection;\n /**\n * Colour of the delta pill. Defaults from direction (up = positive/green,\n * down = negative/red). Override when up is bad (e.g. open incidents rising):\n * pass `deltaTone=\"negative\"` with `deltaDirection=\"up\"`.\n */\n deltaTone?: DeltaTone;\n /** 12-ish point trend for the inline sparkline. Omit to hide it. */\n spark?: number[];\n /** Sparkline colour. Default the amber brand token. */\n sparkColor?: string;\n /** Leading icon (lucide component or any `{ className }` component). */\n icon?: ComponentType<{ className?: string }>;\n /** Promote to the hero tile (stronger glass + accent glow). */\n hero?: boolean;\n className?: string;\n}\n\nconst TONE_PILL: Record<DeltaTone, string> = {\n positive: 'bg-status-success-subtle text-status-success-text',\n negative: 'bg-status-error-subtle text-status-error-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nconst DIRECTION_ICON: Record<DeltaDirection, ComponentType<{ className?: string }>> = {\n up: ArrowUpRight,\n down: ArrowDownRight,\n neutral: Minus,\n};\n\nfunction toneFromDirection(direction: DeltaDirection): DeltaTone {\n if (direction === 'up') return 'positive';\n if (direction === 'down') return 'negative';\n return 'neutral';\n}\n\n/**\n * StatTile — a polished KPI card (GlassCard) with a big proportional figure, an\n * optional signed delta pill and an optional inline sparkline. Replaces the\n * plain label+number cards across AssetHandler. Token-only; no hover movement\n * (the GlassCard only intensifies its glow).\n */\nexport function StatTile({\n label,\n value,\n format,\n delta,\n deltaDirection = 'neutral',\n deltaTone,\n spark,\n sparkColor,\n icon: Icon,\n hero = false,\n className,\n}: StatTileProps) {\n const display =\n typeof value === 'number' ? (format ? format(value) : value.toLocaleString()) : value;\n const tone = deltaTone ?? toneFromDirection(deltaDirection);\n const DeltaIcon = DIRECTION_ICON[deltaDirection];\n const hasSpark = Array.isArray(spark) && spark.length > 1;\n\n return (\n <GlassCard\n treatment={hero ? 'glass' : 'metric'}\n glow={hero}\n className={cn('border-border-seam', className)}\n >\n <div className=\"flex flex-col gap-3 p-5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-secondary\">{label}</span>\n {Icon ? <Icon className=\"h-4 w-4 shrink-0 text-text-muted\" /> : null}\n </div>\n\n <div className=\"flex items-end justify-between gap-3\">\n <span className=\"text-3xl font-bold leading-none text-text-primary\">{display}</span>\n {delta !== undefined && delta !== '' ? (\n <span\n className={cn(\n 'inline-flex shrink-0 items-center gap-0.5 rounded-full px-2 py-0.5 text-xs font-medium',\n TONE_PILL[tone]\n )}\n >\n <DeltaIcon className=\"h-3 w-3\" aria-hidden=\"true\" />\n {delta}\n </span>\n ) : null}\n </div>\n\n {hasSpark ? (\n <Sparkline\n data={spark}\n height={36}\n color={sparkColor}\n ariaLabel={`${label} trend`}\n className=\"mt-0.5\"\n />\n ) : null}\n </div>\n </GlassCard>\n );\n}\n"],"mappings":";;;;;;;AAqCA,IAAM,IAAuC;CAC3C,UAAU;CACV,UAAU;CACV,SAAS;CACV,EAEK,IAAgF;CACpF,IAAI;CACJ,MAAM;CACN,SAAS;CACV;AAED,SAAS,EAAkB,GAAsC;AAG/D,QAFI,MAAc,OAAa,aAC3B,MAAc,SAAe,aAC1B;;AAST,SAAgB,EAAS,EACvB,UACA,UACA,WACA,UACA,oBAAiB,WACjB,cACA,UACA,eACA,MAAM,GACN,UAAO,IACP,gBACgB;CAChB,IAAM,IACJ,OAAO,KAAU,WAAY,IAAS,EAAO,EAAM,GAAG,EAAM,gBAAgB,GAAI,GAC5E,IAAO,KAAa,EAAkB,EAAe,EACrD,IAAY,EAAe,IAC3B,IAAW,MAAM,QAAQ,EAAM,IAAI,EAAM,SAAS;AAExD,QACE,kBAAC,GAAD;EACE,WAAW,IAAO,UAAU;EAC5B,MAAM;EACN,WAAW,EAAG,sBAAsB,EAAU;YAE9C,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,QAAD;MAAM,WAAU;gBAA2C;MAAa,CAAA,EACvE,IAAO,kBAAC,GAAD,EAAM,WAAU,oCAAqC,CAAA,GAAG,KAC5D;;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAqD;MAAe,CAAA,EACnF,MAAU,KAAA,KAAa,MAAU,KAChC,kBAAC,QAAD;MACE,WAAW,EACT,0FACA,EAAU,GACX;gBAJH,CAME,kBAAC,GAAD;OAAW,WAAU;OAAU,eAAY;OAAS,CAAA,EACnD,EACI;UACL,KACA;;IAEL,IACC,kBAAC,GAAD;KACE,MAAM;KACN,QAAQ;KACR,OAAO;KACP,WAAW,GAAG,EAAM;KACpB,WAAU;KACV,CAAA,GACA;IACA;;EACI,CAAA"}
1
+ {"version":3,"file":"StatTile.js","names":[],"sources":["../../../src/assethandler/components/StatTile.tsx"],"sourcesContent":["import type { ComponentType } from 'react';\nimport { ArrowDownRight, ArrowUpRight, Minus } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { Sparkline } from './charts';\n\ntype DeltaDirection = 'up' | 'down' | 'neutral';\ntype DeltaTone = 'positive' | 'negative' | 'neutral';\n\nexport interface StatTileProps {\n /** Metric name, sentence case, no trailing colon. */\n label: string;\n /** The headline figure. Numbers are formatted (default `toLocaleString`). */\n value: string | number;\n /** Formats a numeric `value` (e.g. compact / currency). */\n format?: (value: number) => string;\n /** Optional change pill text, e.g. `\"+12%\"` or `\"3 more\"`. */\n delta?: string | number;\n /** Arrow direction of the change. */\n deltaDirection?: DeltaDirection;\n /**\n * Colour of the delta pill. Defaults from direction (up = positive/green,\n * down = negative/red). Override when up is bad (e.g. open incidents rising):\n * pass `deltaTone=\"negative\"` with `deltaDirection=\"up\"`.\n */\n deltaTone?: DeltaTone;\n /** 12-ish point trend for the inline sparkline. Omit to hide it. */\n spark?: number[];\n /** Sparkline colour. Default the amber brand token. */\n sparkColor?: string;\n /** Leading icon (lucide component or any `{ className }` component). */\n icon?: ComponentType<{ className?: string }>;\n /** Promote to the hero tile (stronger glass + accent glow). */\n hero?: boolean;\n className?: string;\n}\n\nconst TONE_PILL: Record<DeltaTone, string> = {\n positive: 'bg-status-success-subtle text-status-success-text',\n negative: 'bg-status-error-subtle text-status-error-text',\n neutral: 'bg-bg-sunken text-text-secondary',\n};\n\nconst DIRECTION_ICON: Record<DeltaDirection, ComponentType<{ className?: string }>> = {\n up: ArrowUpRight,\n down: ArrowDownRight,\n neutral: Minus,\n};\n\nfunction toneFromDirection(direction: DeltaDirection): DeltaTone {\n if (direction === 'up') return 'positive';\n if (direction === 'down') return 'negative';\n return 'neutral';\n}\n\n/**\n * StatTile — a polished KPI card (GlassCard) with a big proportional figure, an\n * optional signed delta pill and an optional inline sparkline. Replaces the\n * plain label+number cards across AssetHandler. Token-only; no hover movement\n * (the GlassCard only intensifies its glow).\n */\nexport function StatTile({\n label,\n value,\n format,\n delta,\n deltaDirection = 'neutral',\n deltaTone,\n spark,\n sparkColor,\n icon: Icon,\n hero = false,\n className,\n}: StatTileProps) {\n const display =\n typeof value === 'number' ? (format ? format(value) : value.toLocaleString()) : value;\n const tone = deltaTone ?? toneFromDirection(deltaDirection);\n const DeltaIcon = DIRECTION_ICON[deltaDirection];\n const hasSpark = Array.isArray(spark) && spark.length > 1;\n\n return (\n <GlassCard\n treatment={hero ? 'glass' : 'metric'}\n glow={hero}\n className={cn('border-border-seam', className)}\n >\n <div className=\"flex flex-col gap-3 p-5\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-secondary\">{label}</span>\n {Icon ? <Icon className=\"h-4 w-4 shrink-0 text-text-muted\" /> : null}\n </div>\n\n <div className=\"flex items-end justify-between gap-3\">\n <span className=\"text-3xl font-bold leading-none text-text-primary\">{display}</span>\n {delta !== undefined && delta !== '' ? (\n <span\n className={cn(\n 'inline-flex shrink-0 items-center gap-0.5 rounded-full px-2 py-0.5 text-xs font-medium',\n TONE_PILL[tone]\n )}\n >\n <DeltaIcon className=\"h-3 w-3\" aria-hidden=\"true\" />\n {delta}\n </span>\n ) : null}\n </div>\n\n {hasSpark ? (\n <Sparkline\n data={spark}\n height={36}\n color={sparkColor}\n ariaLabel={`${label} trend`}\n className=\"mt-0.5\"\n />\n ) : null}\n </div>\n </GlassCard>\n );\n}\n"],"mappings":";;;;;;;AAqCA,IAAM,IAAuC;CAC3C,UAAU;CACV,UAAU;CACV,SAAS;AACX,GAEM,IAAgF;CACpF,IAAI;CACJ,MAAM;CACN,SAAS;AACX;AAEA,SAAS,EAAkB,GAAsC;CAG/D,OAFI,MAAc,OAAa,aAC3B,MAAc,SAAe,aAC1B;AACT;AAQA,SAAgB,EAAS,EACvB,UACA,UACA,WACA,UACA,oBAAiB,WACjB,cACA,UACA,eACA,MAAM,GACN,UAAO,IACP,gBACgB;CAChB,IAAM,IACJ,OAAO,KAAU,WAAY,IAAS,EAAO,CAAK,IAAI,EAAM,eAAe,IAAK,GAC5E,IAAO,KAAa,EAAkB,CAAc,GACpD,IAAY,EAAe,IAC3B,IAAW,MAAM,QAAQ,CAAK,KAAK,EAAM,SAAS;CAExD,OACE,kBAAC,GAAD;EACE,WAAW,IAAO,UAAU;EAC5B,MAAM;EACN,WAAW,EAAG,sBAAsB,CAAS;YAE7C,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,QAAD;MAAM,WAAU;gBAA2C;KAAY,CAAA,GACtE,IAAO,kBAAC,GAAD,EAAM,WAAU,mCAAoC,CAAA,IAAI,IAC7D;;IAEL,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,QAAD;MAAM,WAAU;gBAAqD;KAAc,CAAA,GAClF,MAAU,KAAA,KAAa,MAAU,KAChC,kBAAC,QAAD;MACE,WAAW,EACT,0FACA,EAAU,EACZ;gBAJF,CAME,kBAAC,GAAD;OAAW,WAAU;OAAU,eAAY;MAAQ,CAAA,GAClD,CACG;UACJ,IACD;;IAEJ,IACC,kBAAC,GAAD;KACE,MAAM;KACN,QAAQ;KACR,OAAO;KACP,WAAW,GAAG,EAAM;KACpB,WAAU;IACX,CAAA,IACC;GACD;;CACI,CAAA;AAEf"}
@@ -1 +1 @@
1
- {"version":3,"file":"BarsChart.js","names":[],"sources":["../../../../src/assethandler/components/charts/BarsChart.tsx"],"sourcesContent":["import {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport {\n chartTokens,\n defaultSeriesColor,\n formatNumber,\n usePrefersReducedMotion,\n type ChartDatum,\n type ChartSeries,\n type ValueFormatter,\n} from './chartTheme';\nimport { ChartDataTable, ChartEmpty, ChartFigure, ChartLegend, ChartTooltip } from './ChartParts';\n\nexport interface BarsChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the category label. */\n xKey: string;\n /** One or more numeric series. */\n series: ChartSeries[];\n /** `vertical` = columns growing up (default); `horizontal` = bars growing right. */\n orientation?: 'vertical' | 'horizontal';\n /** Stack the series instead of grouping side-by-side. Default false. */\n stacked?: boolean;\n /** Pixel height. Default 260. */\n height?: number;\n /** Formats numeric values in the axis + tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats the category tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the value-axis grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Width of the category label column in `horizontal` mode. Default 96. */\n categoryWidth?: number;\n /** Message shown when `data` is empty. */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * BarsChart — categorical magnitude as columns or horizontal bars, grouped or\n * stacked. Thin (≤ 24px) marks with 4px rounded data-ends, a hairline grid, a\n * per-mark tooltip, a multi-series legend, an empty state and a screen-reader\n * table. Colour is identity only (never re-encoding the bar's length).\n */\nexport function BarsChart({\n data,\n xKey,\n series,\n orientation = 'vertical',\n stacked = false,\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n categoryWidth = 96,\n emptyLabel,\n ariaLabel,\n className,\n}: BarsChartProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const resolved = series.map((s, index) => ({\n ...s,\n label: s.label ?? s.key,\n color: s.color ?? defaultSeriesColor(index, series.length),\n }));\n const label = ariaLabel ?? `${resolved.map((s) => s.label).join(', ')} by ${xKey}`;\n\n if (data.length === 0) {\n return <ChartEmpty height={height} label={emptyLabel} className={className} />;\n }\n\n const isColumns = orientation === 'vertical';\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n const lastIndex = resolved.length - 1;\n\n /** Rounded data-end: columns round the top, horizontal bars the right; a stack\n * rounds only its outermost (last) segment. */\n const radiusFor = (index: number): [number, number, number, number] => {\n const rounded = !stacked || index === lastIndex;\n if (!rounded) return [0, 0, 0, 0];\n return isColumns ? [4, 4, 0, 0] : [0, 4, 4, 0];\n };\n\n const stackId = stacked ? 'stack' : undefined;\n\n return (\n <ChartFigure\n ariaLabel={label}\n height={height}\n className={className}\n a11y={\n <ChartDataTable\n caption={label}\n xLabel={xKey}\n xKey={xKey}\n data={data}\n series={resolved}\n valueFormat={valueFormat}\n />\n }\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart\n data={data}\n layout={isColumns ? 'horizontal' : 'vertical'}\n margin={{ top: 8, right: 16, bottom: 4, left: 4 }}\n barCategoryGap={isColumns ? '24%' : '28%'}\n >\n {showGrid ? (\n <CartesianGrid\n vertical={!isColumns}\n horizontal={isColumns}\n stroke={chartTokens.grid}\n strokeWidth={1}\n />\n ) : null}\n\n {isColumns ? (\n <>\n <XAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n tickFormatter={\n xTickFormat ? (value) => xTickFormat(value as string | number) : undefined\n }\n />\n <YAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n </>\n ) : (\n <>\n <XAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n <YAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={categoryWidth}\n tickFormatter={\n xTickFormat ? (value) => xTickFormat(value as string | number) : undefined\n }\n />\n </>\n )}\n\n <Tooltip\n cursor={{ fill: chartTokens.track, opacity: 0.5 }}\n content={<ChartTooltip valueFormat={valueFormat} labelFormat={xTickFormat} />}\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) => (\n <Bar\n key={s.key}\n dataKey={s.key}\n name={s.label}\n fill={s.color}\n stackId={stackId}\n maxBarSize={24}\n radius={radiusFor(index)}\n isAnimationActive={!reducedMotion}\n />\n ))}\n </BarChart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAyDA,SAAgB,EAAU,EACxB,SACA,SACA,WACA,iBAAc,YACd,aAAU,IACV,YAAS,KACT,iBAAc,GACd,gBACA,cAAW,IACX,eACA,mBAAgB,IAChB,eACA,cACA,gBACiB;CACjB,IAAM,IAAgB,GAAyB,EAEzC,IAAW,EAAO,KAAK,GAAG,OAAW;EACzC,GAAG;EACH,OAAO,EAAE,SAAS,EAAE;EACpB,OAAO,EAAE,SAAS,EAAmB,GAAO,EAAO,OAAO;EAC3D,EAAE,EACG,IAAQ,KAAa,GAAG,EAAS,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK,CAAC,MAAM;AAE5E,KAAI,EAAK,WAAW,EAClB,QAAO,kBAAC,GAAD;EAAoB;EAAQ,OAAO;EAAuB;EAAa,CAAA;CAGhF,IAAM,IAAY,MAAgB,YAC5B,IAAa,KAAc,EAAS,SAAS,GAC7C,IAAW;EAAE,MAAM,EAAY;EAAW,UAAU;EAAI,EACxD,IAAY,EAAS,SAAS,GAI9B,KAAa,MACD,CAAC,KAAW,MAAU,IAE/B,IAAY;EAAC;EAAG;EAAG;EAAG;EAAE,GAAG;EAAC;EAAG;EAAG;EAAG;EAAE,GADzB;EAAC;EAAG;EAAG;EAAG;EAAE,EAI7B,IAAU,IAAU,UAAU,KAAA;AAEpC,QACE,kBAAC,GAAD;EACE,WAAW;EACH;EACG;EACX,MACE,kBAAC,GAAD;GACE,SAAS;GACT,QAAQ;GACF;GACA;GACN,QAAQ;GACK;GACb,CAAA;YAGJ,kBAAC,GAAD;GAAqB,OAAM;GAAO,QAAO;aACvC,kBAAC,GAAD;IACQ;IACN,QAAQ,IAAY,eAAe;IACnC,QAAQ;KAAE,KAAK;KAAG,OAAO;KAAI,QAAQ;KAAG,MAAM;KAAG;IACjD,gBAAgB,IAAY,QAAQ;cAJtC;KAMG,IACC,kBAAC,GAAD;MACE,UAAU,CAAC;MACX,YAAY;MACZ,QAAQ,EAAY;MACpB,aAAa;MACb,CAAA,GACA;KAEH,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,SAAS;MACT,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,YAAY;MACZ,eACE,KAAe,MAAU,EAAY,EAAyB,GAAG,KAAA;MAEnE,CAAA,EACF,kBAAC,GAAD;MACE,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,OAAO;MACP,gBAAgB,MAAU,EAAY,OAAO,EAAM,CAAC;MACpD,CAAA,CACD,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,gBAAgB,MAAU,EAAY,OAAO,EAAM,CAAC;MACpD,CAAA,EACF,kBAAC,GAAD;MACE,SAAS;MACT,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,OAAO;MACP,eACE,KAAe,MAAU,EAAY,EAAyB,GAAG,KAAA;MAEnE,CAAA,CACD,EAAA,CAAA;KAGL,kBAAC,GAAD;MACE,QAAQ;OAAE,MAAM,EAAY;OAAO,SAAS;OAAK;MACjD,SAAS,kBAAC,GAAD;OAA2B;OAAa,aAAa;OAAe,CAAA;MAC7E,CAAA;KAED,IAAa,kBAAC,GAAD,EAAQ,SAAS,kBAAC,GAAD,EAAe,CAAA,EAAI,CAAA,GAAG;KAEpD,EAAS,KAAK,GAAG,MAChB,kBAAC,GAAD;MAEE,SAAS,EAAE;MACX,MAAM,EAAE;MACR,MAAM,EAAE;MACC;MACT,YAAY;MACZ,QAAQ,EAAU,EAAM;MACxB,mBAAmB,CAAC;MACpB,EARK,EAAE,IAQP,CACF;KACO;;GACS,CAAA;EACV,CAAA"}
1
+ {"version":3,"file":"BarsChart.js","names":[],"sources":["../../../../src/assethandler/components/charts/BarsChart.tsx"],"sourcesContent":["import {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport {\n chartTokens,\n defaultSeriesColor,\n formatNumber,\n usePrefersReducedMotion,\n type ChartDatum,\n type ChartSeries,\n type ValueFormatter,\n} from './chartTheme';\nimport { ChartDataTable, ChartEmpty, ChartFigure, ChartLegend, ChartTooltip } from './ChartParts';\n\nexport interface BarsChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the category label. */\n xKey: string;\n /** One or more numeric series. */\n series: ChartSeries[];\n /** `vertical` = columns growing up (default); `horizontal` = bars growing right. */\n orientation?: 'vertical' | 'horizontal';\n /** Stack the series instead of grouping side-by-side. Default false. */\n stacked?: boolean;\n /** Pixel height. Default 260. */\n height?: number;\n /** Formats numeric values in the axis + tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats the category tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the value-axis grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Width of the category label column in `horizontal` mode. Default 96. */\n categoryWidth?: number;\n /** Message shown when `data` is empty. */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * BarsChart — categorical magnitude as columns or horizontal bars, grouped or\n * stacked. Thin (≤ 24px) marks with 4px rounded data-ends, a hairline grid, a\n * per-mark tooltip, a multi-series legend, an empty state and a screen-reader\n * table. Colour is identity only (never re-encoding the bar's length).\n */\nexport function BarsChart({\n data,\n xKey,\n series,\n orientation = 'vertical',\n stacked = false,\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n categoryWidth = 96,\n emptyLabel,\n ariaLabel,\n className,\n}: BarsChartProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const resolved = series.map((s, index) => ({\n ...s,\n label: s.label ?? s.key,\n color: s.color ?? defaultSeriesColor(index, series.length),\n }));\n const label = ariaLabel ?? `${resolved.map((s) => s.label).join(', ')} by ${xKey}`;\n\n if (data.length === 0) {\n return <ChartEmpty height={height} label={emptyLabel} className={className} />;\n }\n\n const isColumns = orientation === 'vertical';\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n const lastIndex = resolved.length - 1;\n\n /** Rounded data-end: columns round the top, horizontal bars the right; a stack\n * rounds only its outermost (last) segment. */\n const radiusFor = (index: number): [number, number, number, number] => {\n const rounded = !stacked || index === lastIndex;\n if (!rounded) return [0, 0, 0, 0];\n return isColumns ? [4, 4, 0, 0] : [0, 4, 4, 0];\n };\n\n const stackId = stacked ? 'stack' : undefined;\n\n return (\n <ChartFigure\n ariaLabel={label}\n height={height}\n className={className}\n a11y={\n <ChartDataTable\n caption={label}\n xLabel={xKey}\n xKey={xKey}\n data={data}\n series={resolved}\n valueFormat={valueFormat}\n />\n }\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart\n data={data}\n layout={isColumns ? 'horizontal' : 'vertical'}\n margin={{ top: 8, right: 16, bottom: 4, left: 4 }}\n barCategoryGap={isColumns ? '24%' : '28%'}\n >\n {showGrid ? (\n <CartesianGrid\n vertical={!isColumns}\n horizontal={isColumns}\n stroke={chartTokens.grid}\n strokeWidth={1}\n />\n ) : null}\n\n {isColumns ? (\n <>\n <XAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n tickFormatter={\n xTickFormat ? (value) => xTickFormat(value as string | number) : undefined\n }\n />\n <YAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n </>\n ) : (\n <>\n <XAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n <YAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={categoryWidth}\n tickFormatter={\n xTickFormat ? (value) => xTickFormat(value as string | number) : undefined\n }\n />\n </>\n )}\n\n <Tooltip\n cursor={{ fill: chartTokens.track, opacity: 0.5 }}\n content={<ChartTooltip valueFormat={valueFormat} labelFormat={xTickFormat} />}\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) => (\n <Bar\n key={s.key}\n dataKey={s.key}\n name={s.label}\n fill={s.color}\n stackId={stackId}\n maxBarSize={24}\n radius={radiusFor(index)}\n isAnimationActive={!reducedMotion}\n />\n ))}\n </BarChart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChartParts.js","names":[],"sources":["../../../../src/assethandler/components/charts/ChartParts.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport { Inbox } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n chartTokens,\n renderValue,\n type ValueFormatter,\n type ChartDatum,\n type ChartSeries,\n} from './chartTheme';\n\n/**\n * Shared chart chrome — the tooltip, legend, empty state and screen-reader data\n * table used by every recharts primitive in this folder. Kept token-only so the\n * whole set recolours with the theme.\n */\n\n/* -------------------------------------------------------------------------- */\n/* Tooltip */\n/* -------------------------------------------------------------------------- */\n\ninterface TooltipPayloadEntry {\n name?: string | number;\n value?: number | string;\n color?: string;\n dataKey?: string | number;\n}\n\nexport interface ChartTooltipProps {\n /** Injected by recharts. */\n active?: boolean;\n /** Injected by recharts. */\n payload?: TooltipPayloadEntry[];\n /** Injected by recharts. */\n label?: string | number;\n valueFormat?: ValueFormatter;\n labelFormat?: (label: string | number) => string;\n /** Hide the header row (used by single-series / donut tooltips). */\n hideLabel?: boolean;\n}\n\n/**\n * Token-styled tooltip card. Identity rides a colour swatch beside the name;\n * every text run stays in an ink token, never the series colour.\n */\nexport function ChartTooltip({\n active,\n payload,\n label,\n valueFormat,\n labelFormat,\n hideLabel,\n}: ChartTooltipProps) {\n if (!active || !payload || payload.length === 0) return null;\n\n return (\n <div className=\"min-w-32 rounded-lg border border-border-seam bg-bg-surface/95 px-3 py-2 shadow-lg backdrop-blur-sm\">\n {!hideLabel && label !== undefined && label !== '' ? (\n <p className=\"mb-1.5 text-xs font-medium text-text-secondary\">\n {labelFormat ? labelFormat(label) : String(label)}\n </p>\n ) : null}\n <ul className=\"space-y-1\">\n {payload.map((entry, index) => (\n <li\n key={`${String(entry.dataKey ?? entry.name ?? index)}`}\n className=\"flex items-center justify-between gap-4 text-sm\"\n >\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 shrink-0 rounded-[3px]\"\n style={{ backgroundColor: entry.color ?? chartTokens.brand }}\n />\n <span className=\"truncate text-text-secondary\">{entry.name ?? entry.dataKey}</span>\n </span>\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {renderValue(entry.value, valueFormat)}\n </span>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Legend */\n/* -------------------------------------------------------------------------- */\n\ninterface LegendPayloadEntry {\n value?: string | number;\n color?: string;\n}\n\nexport interface ChartLegendProps {\n /** Injected by recharts. */\n payload?: LegendPayloadEntry[];\n}\n\n/**\n * Token-styled legend — always present for ≥ 2 series so identity is never\n * carried by colour alone. Text is muted ink; the colour lives in the swatch.\n */\nexport function ChartLegend({ payload }: ChartLegendProps) {\n if (!payload || payload.length === 0) return null;\n return (\n <ul className=\"flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5 pt-3\">\n {payload.map((entry, index) => (\n <li\n key={`${String(entry.value ?? index)}`}\n className=\"flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: entry.color ?? chartTokens.brand }}\n />\n {entry.value}\n </li>\n ))}\n </ul>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Empty state */\n/* -------------------------------------------------------------------------- */\n\nexport interface ChartEmptyProps {\n /** Height of the placeholder, matched to the chart it stands in for. */\n height?: number;\n /** Muted message. Never fabricate data — show this instead. */\n label?: string;\n className?: string;\n}\n\n/** Calm \"no data yet\" placeholder. Rendered whenever a series is empty. */\nexport function ChartEmpty({ height = 240, label = 'No data yet', className }: ChartEmptyProps) {\n return (\n <div\n className={cn(\n 'flex w-full flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border-seam bg-bg-sunken/40 text-center',\n className\n )}\n style={{ height }}\n >\n <Inbox className=\"h-6 w-6 text-text-muted\" aria-hidden=\"true\" />\n <p className=\"text-sm text-text-muted\">{label}</p>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Screen-reader data table (accessibility relief channel) */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Visually-hidden style, applied inline so it never depends on the host's\n * Tailwind build emitting the `sr-only` utility. Keeps the a11y data tables out\n * of sight while readable by assistive tech in every environment.\n */\nexport const srOnlyStyle: CSSProperties = {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: 0,\n margin: '-1px',\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n borderWidth: 0,\n};\n\nexport interface ChartDataTableProps {\n caption: string;\n xLabel: string;\n xKey: string;\n data: ChartDatum[];\n series: ChartSeries[];\n valueFormat?: ValueFormatter;\n}\n\n/**\n * Visually-hidden table mirroring the plotted data. Satisfies the data-viz\n * \"a table view exists\" accessibility requirement and gives assistive tech the\n * exact numbers behind the marks.\n */\nexport function ChartDataTable({\n caption,\n xLabel,\n xKey,\n data,\n series,\n valueFormat,\n}: ChartDataTableProps) {\n return (\n <table style={srOnlyStyle}>\n <caption>{caption}</caption>\n <thead>\n <tr>\n <th scope=\"col\">{xLabel}</th>\n {series.map((s) => (\n <th scope=\"col\" key={s.key}>\n {s.label ?? s.key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((row, index) => (\n <tr key={`${String(row[xKey] ?? index)}`}>\n <th scope=\"row\">{String(row[xKey] ?? '')}</th>\n {series.map((s) => (\n <td key={s.key}>{renderValue(row[s.key] as number | string, valueFormat)}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Figure wrapper */\n/* -------------------------------------------------------------------------- */\n\nexport interface ChartFigureProps {\n /** Accessible name for the whole figure. */\n ariaLabel: string;\n height: number;\n children: ReactNode;\n /** Screen-reader table + any extra off-screen content. */\n a11y?: ReactNode;\n className?: string;\n}\n\n/** `role=\"img\"` wrapper giving the chart a single accessible name + fixed height. */\nexport function ChartFigure({ ariaLabel, height, children, a11y, className }: ChartFigureProps) {\n return (\n <figure role=\"img\" aria-label={ariaLabel} className={cn('w-full', className)}>\n <div style={{ height }}>{children}</div>\n {a11y}\n </figure>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ChartParts.js","names":[],"sources":["../../../../src/assethandler/components/charts/ChartParts.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react';\nimport { Inbox } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport {\n chartTokens,\n renderValue,\n type ValueFormatter,\n type ChartDatum,\n type ChartSeries,\n} from './chartTheme';\n\n/**\n * Shared chart chrome — the tooltip, legend, empty state and screen-reader data\n * table used by every recharts primitive in this folder. Kept token-only so the\n * whole set recolours with the theme.\n */\n\n/* -------------------------------------------------------------------------- */\n/* Tooltip */\n/* -------------------------------------------------------------------------- */\n\ninterface TooltipPayloadEntry {\n name?: string | number;\n value?: number | string;\n color?: string;\n dataKey?: string | number;\n}\n\nexport interface ChartTooltipProps {\n /** Injected by recharts. */\n active?: boolean;\n /** Injected by recharts. */\n payload?: TooltipPayloadEntry[];\n /** Injected by recharts. */\n label?: string | number;\n valueFormat?: ValueFormatter;\n labelFormat?: (label: string | number) => string;\n /** Hide the header row (used by single-series / donut tooltips). */\n hideLabel?: boolean;\n}\n\n/**\n * Token-styled tooltip card. Identity rides a colour swatch beside the name;\n * every text run stays in an ink token, never the series colour.\n */\nexport function ChartTooltip({\n active,\n payload,\n label,\n valueFormat,\n labelFormat,\n hideLabel,\n}: ChartTooltipProps) {\n if (!active || !payload || payload.length === 0) return null;\n\n return (\n <div className=\"min-w-32 rounded-lg border border-border-seam bg-bg-surface/95 px-3 py-2 shadow-lg backdrop-blur-sm\">\n {!hideLabel && label !== undefined && label !== '' ? (\n <p className=\"mb-1.5 text-xs font-medium text-text-secondary\">\n {labelFormat ? labelFormat(label) : String(label)}\n </p>\n ) : null}\n <ul className=\"space-y-1\">\n {payload.map((entry, index) => (\n <li\n key={`${String(entry.dataKey ?? entry.name ?? index)}`}\n className=\"flex items-center justify-between gap-4 text-sm\"\n >\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 shrink-0 rounded-[3px]\"\n style={{ backgroundColor: entry.color ?? chartTokens.brand }}\n />\n <span className=\"truncate text-text-secondary\">{entry.name ?? entry.dataKey}</span>\n </span>\n <span className=\"font-semibold tabular-nums text-text-primary\">\n {renderValue(entry.value, valueFormat)}\n </span>\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Legend */\n/* -------------------------------------------------------------------------- */\n\ninterface LegendPayloadEntry {\n value?: string | number;\n color?: string;\n}\n\nexport interface ChartLegendProps {\n /** Injected by recharts. */\n payload?: LegendPayloadEntry[];\n}\n\n/**\n * Token-styled legend — always present for ≥ 2 series so identity is never\n * carried by colour alone. Text is muted ink; the colour lives in the swatch.\n */\nexport function ChartLegend({ payload }: ChartLegendProps) {\n if (!payload || payload.length === 0) return null;\n return (\n <ul className=\"flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5 pt-3\">\n {payload.map((entry, index) => (\n <li\n key={`${String(entry.value ?? index)}`}\n className=\"flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: entry.color ?? chartTokens.brand }}\n />\n {entry.value}\n </li>\n ))}\n </ul>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Empty state */\n/* -------------------------------------------------------------------------- */\n\nexport interface ChartEmptyProps {\n /** Height of the placeholder, matched to the chart it stands in for. */\n height?: number;\n /** Muted message. Never fabricate data — show this instead. */\n label?: string;\n className?: string;\n}\n\n/** Calm \"no data yet\" placeholder. Rendered whenever a series is empty. */\nexport function ChartEmpty({ height = 240, label = 'No data yet', className }: ChartEmptyProps) {\n return (\n <div\n className={cn(\n 'flex w-full flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-border-seam bg-bg-sunken/40 text-center',\n className\n )}\n style={{ height }}\n >\n <Inbox className=\"h-6 w-6 text-text-muted\" aria-hidden=\"true\" />\n <p className=\"text-sm text-text-muted\">{label}</p>\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Screen-reader data table (accessibility relief channel) */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Visually-hidden style, applied inline so it never depends on the host's\n * Tailwind build emitting the `sr-only` utility. Keeps the a11y data tables out\n * of sight while readable by assistive tech in every environment.\n */\nexport const srOnlyStyle: CSSProperties = {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: 0,\n margin: '-1px',\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n borderWidth: 0,\n};\n\nexport interface ChartDataTableProps {\n caption: string;\n xLabel: string;\n xKey: string;\n data: ChartDatum[];\n series: ChartSeries[];\n valueFormat?: ValueFormatter;\n}\n\n/**\n * Visually-hidden table mirroring the plotted data. Satisfies the data-viz\n * \"a table view exists\" accessibility requirement and gives assistive tech the\n * exact numbers behind the marks.\n */\nexport function ChartDataTable({\n caption,\n xLabel,\n xKey,\n data,\n series,\n valueFormat,\n}: ChartDataTableProps) {\n return (\n <table style={srOnlyStyle}>\n <caption>{caption}</caption>\n <thead>\n <tr>\n <th scope=\"col\">{xLabel}</th>\n {series.map((s) => (\n <th scope=\"col\" key={s.key}>\n {s.label ?? s.key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((row, index) => (\n <tr key={`${String(row[xKey] ?? index)}`}>\n <th scope=\"row\">{String(row[xKey] ?? '')}</th>\n {series.map((s) => (\n <td key={s.key}>{renderValue(row[s.key] as number | string, valueFormat)}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Figure wrapper */\n/* -------------------------------------------------------------------------- */\n\nexport interface ChartFigureProps {\n /** Accessible name for the whole figure. */\n ariaLabel: string;\n height: number;\n children: ReactNode;\n /** Screen-reader table + any extra off-screen content. */\n a11y?: ReactNode;\n className?: string;\n}\n\n/** `role=\"img\"` wrapper giving the chart a single accessible name + fixed height. */\nexport function ChartFigure({ ariaLabel, height, children, a11y, className }: ChartFigureProps) {\n return (\n <figure role=\"img\" aria-label={ariaLabel} className={cn('w-full', className)}>\n <div style={{ height }}>{children}</div>\n {a11y}\n </figure>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DonutChart.js","names":[],"sources":["../../../../src/assethandler/components/charts/DonutChart.tsx"],"sourcesContent":["import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from 'recharts';\nimport { cn } from '../../utils/cn';\nimport {\n chartTokens,\n formatNumber,\n renderValue,\n seriesColor,\n usePrefersReducedMotion,\n type DonutSlice,\n type ValueFormatter,\n} from './chartTheme';\nimport { ChartEmpty, ChartTooltip, srOnlyStyle } from './ChartParts';\n\nexport interface DonutChartProps {\n /** Slices `{ name, value, color? }`. */\n data: DonutSlice[];\n /** Small caption under the centre value (e.g. \"Total assets\"). */\n centerLabel?: string;\n /**\n * Big centre value. If omitted while `centerLabel` is set, the summed total is\n * shown. A number is run through `valueFormat`.\n */\n centerValue?: string | number;\n /** Pixel height of the ring. Default 240. */\n height?: number;\n /** Ring thickness as a fraction of the radius (0–1). Default 0.42. */\n thickness?: number;\n /** Formats slice + centre values. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Show the legend list under the ring. Default true. */\n showLegend?: boolean;\n /** Message shown when there are no slices (or all zero). */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * DonutChart — a category/status mix as a ring with a center total. Slices take\n * the categorical ramp in fixed order, identity is carried by an always-present\n * legend (never colour alone), and hover reveals a token-styled tooltip.\n * Renders an empty state — never a fake ring — when there is nothing to show.\n */\nexport function DonutChart({\n data,\n centerLabel,\n centerValue,\n height = 240,\n thickness = 0.42,\n valueFormat = formatNumber,\n showLegend = true,\n emptyLabel,\n ariaLabel,\n className,\n}: DonutChartProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const slices = data\n .filter(\n (slice) => typeof slice.value === 'number' && Number.isFinite(slice.value) && slice.value > 0\n )\n .map((slice, index) => ({ ...slice, color: slice.color ?? seriesColor(index) }));\n\n const total = slices.reduce((sum, slice) => sum + slice.value, 0);\n\n if (slices.length === 0 || total <= 0) {\n return <ChartEmpty height={height} label={emptyLabel} className={className} />;\n }\n\n const label =\n ariaLabel ?? `${centerLabel ?? 'Distribution'}: ${slices.map((s) => s.name).join(', ')}`;\n const outerPct = 82;\n const innerPct = Math.max(0, Math.round(outerPct * (1 - thickness)));\n const showCenter = centerLabel !== undefined || centerValue !== undefined;\n const resolvedCenter =\n centerValue !== undefined ? renderValue(centerValue, valueFormat) : valueFormat(total);\n\n return (\n <figure role=\"img\" aria-label={label} className={cn('w-full', className)}>\n <div className=\"relative mx-auto\" style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <PieChart>\n <Tooltip\n cursor={false}\n content={<ChartTooltip valueFormat={valueFormat} hideLabel />}\n />\n <Pie\n data={slices}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={`${innerPct}%`}\n outerRadius={`${outerPct}%`}\n paddingAngle={1.5}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n >\n {slices.map((slice) => (\n <Cell key={slice.name} fill={slice.color} />\n ))}\n </Pie>\n </PieChart>\n </ResponsiveContainer>\n\n {showCenter ? (\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-2xl font-bold text-text-primary\">{resolvedCenter}</span>\n {centerLabel ? (\n <span className=\"mt-0.5 max-w-[70%] text-xs text-text-secondary\">{centerLabel}</span>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {showLegend ? (\n <ul className=\"mt-3 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5\">\n {slices.map((slice) => (\n <li key={slice.name} className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: slice.color }}\n />\n <span>{slice.name}</span>\n <span className=\"tabular-nums text-text-muted\">\n {Math.round((slice.value / total) * 100)}%\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n\n <table style={srOnlyStyle}>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {slices.map((slice) => (\n <tr key={slice.name}>\n <th scope=\"row\">{slice.name}</th>\n <td>{valueFormat(slice.value)}</td>\n <td>{Math.round((slice.value / total) * 100)}%</td>\n </tr>\n ))}\n </tbody>\n </table>\n </figure>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DonutChart.js","names":[],"sources":["../../../../src/assethandler/components/charts/DonutChart.tsx"],"sourcesContent":["import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from 'recharts';\nimport { cn } from '../../utils/cn';\nimport {\n chartTokens,\n formatNumber,\n renderValue,\n seriesColor,\n usePrefersReducedMotion,\n type DonutSlice,\n type ValueFormatter,\n} from './chartTheme';\nimport { ChartEmpty, ChartTooltip, srOnlyStyle } from './ChartParts';\n\nexport interface DonutChartProps {\n /** Slices `{ name, value, color? }`. */\n data: DonutSlice[];\n /** Small caption under the centre value (e.g. \"Total assets\"). */\n centerLabel?: string;\n /**\n * Big centre value. If omitted while `centerLabel` is set, the summed total is\n * shown. A number is run through `valueFormat`.\n */\n centerValue?: string | number;\n /** Pixel height of the ring. Default 240. */\n height?: number;\n /** Ring thickness as a fraction of the radius (0–1). Default 0.42. */\n thickness?: number;\n /** Formats slice + centre values. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Show the legend list under the ring. Default true. */\n showLegend?: boolean;\n /** Message shown when there are no slices (or all zero). */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * DonutChart — a category/status mix as a ring with a center total. Slices take\n * the categorical ramp in fixed order, identity is carried by an always-present\n * legend (never colour alone), and hover reveals a token-styled tooltip.\n * Renders an empty state — never a fake ring — when there is nothing to show.\n */\nexport function DonutChart({\n data,\n centerLabel,\n centerValue,\n height = 240,\n thickness = 0.42,\n valueFormat = formatNumber,\n showLegend = true,\n emptyLabel,\n ariaLabel,\n className,\n}: DonutChartProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const slices = data\n .filter(\n (slice) => typeof slice.value === 'number' && Number.isFinite(slice.value) && slice.value > 0\n )\n .map((slice, index) => ({ ...slice, color: slice.color ?? seriesColor(index) }));\n\n const total = slices.reduce((sum, slice) => sum + slice.value, 0);\n\n if (slices.length === 0 || total <= 0) {\n return <ChartEmpty height={height} label={emptyLabel} className={className} />;\n }\n\n const label =\n ariaLabel ?? `${centerLabel ?? 'Distribution'}: ${slices.map((s) => s.name).join(', ')}`;\n const outerPct = 82;\n const innerPct = Math.max(0, Math.round(outerPct * (1 - thickness)));\n const showCenter = centerLabel !== undefined || centerValue !== undefined;\n const resolvedCenter =\n centerValue !== undefined ? renderValue(centerValue, valueFormat) : valueFormat(total);\n\n return (\n <figure role=\"img\" aria-label={label} className={cn('w-full', className)}>\n <div className=\"relative mx-auto\" style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <PieChart>\n <Tooltip\n cursor={false}\n content={<ChartTooltip valueFormat={valueFormat} hideLabel />}\n />\n <Pie\n data={slices}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={`${innerPct}%`}\n outerRadius={`${outerPct}%`}\n paddingAngle={1.5}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n >\n {slices.map((slice) => (\n <Cell key={slice.name} fill={slice.color} />\n ))}\n </Pie>\n </PieChart>\n </ResponsiveContainer>\n\n {showCenter ? (\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-2xl font-bold text-text-primary\">{resolvedCenter}</span>\n {centerLabel ? (\n <span className=\"mt-0.5 max-w-[70%] text-xs text-text-secondary\">{centerLabel}</span>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {showLegend ? (\n <ul className=\"mt-3 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5\">\n {slices.map((slice) => (\n <li key={slice.name} className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: slice.color }}\n />\n <span>{slice.name}</span>\n <span className=\"tabular-nums text-text-muted\">\n {Math.round((slice.value / total) * 100)}%\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n\n <table style={srOnlyStyle}>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {slices.map((slice) => (\n <tr key={slice.name}>\n <th scope=\"row\">{slice.name}</th>\n <td>{valueFormat(slice.value)}</td>\n <td>{Math.round((slice.value / total) * 100)}%</td>\n </tr>\n ))}\n </tbody>\n </table>\n </figure>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProgressMeter.js","names":[],"sources":["../../../../src/assethandler/components/charts/ProgressMeter.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport { toneColor, type MeterTone, type ValueFormatter } from './chartTheme';\n\nexport interface ProgressMeterProps {\n /** Current value. */\n value: number;\n /** Full-scale value. Default 100. */\n max?: number;\n /** Leading caption (e.g. \"Seats used\", \"Budget spent\"). */\n label?: ReactNode;\n /**\n * Severity thresholds as fractions of `max` (0–1). With the default\n * `higherIsWorse` a fraction ≥ `danger` turns the fill red, ≥ `warning` amber.\n * Default `{ warning: 0.75, danger: 0.9 }`.\n */\n thresholds?: { warning: number; danger: number };\n /** Whether a fuller meter is worse (usage/budget, default) or better (progress). */\n higherIsWorse?: boolean;\n /** Force a tone, bypassing thresholds. */\n tone?: MeterTone;\n /** Show the `value / max` readout on the right of the label row. Default true. */\n showValue?: boolean;\n /** Formats the value + max readout. Default grouped integer. */\n format?: ValueFormatter;\n /** Bar thickness. Default `md`. */\n size?: 'sm' | 'md' | 'lg';\n className?: string;\n}\n\nconst TRACK_HEIGHT: Record<NonNullable<ProgressMeterProps['size']>, string> = {\n sm: 'h-1.5',\n md: 'h-2.5',\n lg: 'h-3.5',\n};\n\nconst defaultFormat: ValueFormatter = (value) => value.toLocaleString();\n\n/**\n * ProgressMeter — a linear meter for a single ratio (seat usage, budget spent,\n * progress to target). The fill carries severity (good → warning → danger) via\n * reserved status tokens over a muted track; the width transition is gated\n * behind `motion-safe` so reduced-motion users get an instant fill. Token-only,\n * no raw colour.\n */\nexport function ProgressMeter({\n value,\n max = 100,\n label,\n thresholds = { warning: 0.75, danger: 0.9 },\n higherIsWorse = true,\n tone,\n showValue = true,\n format = defaultFormat,\n size = 'md',\n className,\n}: ProgressMeterProps) {\n const safeMax = max > 0 ? max : 1;\n const fraction = Math.min(1, Math.max(0, value / safeMax));\n const pct = Math.round(fraction * 100);\n\n const resolvedTone: MeterTone =\n tone ??\n (higherIsWorse\n ? fraction >= thresholds.danger\n ? 'danger'\n : fraction >= thresholds.warning\n ? 'warning'\n : 'success'\n : fraction >= thresholds.warning\n ? 'success'\n : fraction >= thresholds.danger\n ? 'warning'\n : 'danger');\n\n const fillColor = toneColor(resolvedTone);\n\n return (\n <div className={cn('w-full', className)}>\n {label !== undefined || showValue ? (\n <div className=\"mb-1.5 flex items-center justify-between gap-3 text-sm\">\n {label !== undefined ? (\n <span className=\"min-w-0 truncate font-medium text-text-primary\">{label}</span>\n ) : (\n <span />\n )}\n {showValue ? (\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {format(value)}\n <span className=\"text-text-muted\"> / {format(max)}</span>\n </span>\n ) : null}\n </div>\n ) : null}\n\n <div\n className={cn('w-full overflow-hidden rounded-full bg-bg-sunken', TRACK_HEIGHT[size])}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={typeof label === 'string' ? label : undefined}\n >\n <div\n className=\"h-full rounded-full motion-safe:transition-[width] motion-safe:duration-500\"\n style={{ width: `${pct}%`, backgroundColor: fillColor }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;AA8BA,IAAM,IAAwE;CAC5E,IAAI;CACJ,IAAI;CACJ,IAAI;CACL,EAEK,KAAiC,MAAU,EAAM,gBAAgB;AASvE,SAAgB,EAAc,EAC5B,UACA,SAAM,KACN,UACA,gBAAa;CAAE,SAAS;CAAM,QAAQ;CAAK,EAC3C,mBAAgB,IAChB,SACA,eAAY,IACZ,YAAS,GACT,UAAO,MACP,gBACqB;CAErB,IAAM,IAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KADzB,IAAM,IAAI,IAAM,GACyB,CAAC,EACpD,IAAM,KAAK,MAAM,IAAW,IAAI,EAgBhC,IAAY,EAbhB,MACC,IACG,KAAY,EAAW,SACrB,WACA,KAAY,EAAW,UACrB,YACA,YACJ,KAAY,EAAW,UACrB,YACA,KAAY,EAAW,SACrB,YACA,UAE+B;AAEzC,QACE,kBAAC,OAAD;EAAK,WAAW,EAAG,UAAU,EAAU;YAAvC,CACG,MAAU,KAAA,KAAa,IACtB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,MAAU,KAAA,IAGT,kBAAC,QAAD,EAAQ,CAAA,GAFR,kBAAC,QAAD;IAAM,WAAU;cAAkD;IAAa,CAAA,EAIhF,IACC,kBAAC,QAAD;IAAM,WAAU;cAAhB,CACG,EAAO,EAAM,EACd,kBAAC,QAAD;KAAM,WAAU;eAAhB,CAAkC,OAAI,EAAO,EAAI,CAAQ;OACpD;QACL,KACA;OACJ,MAEJ,kBAAC,OAAD;GACE,WAAW,EAAG,oDAAoD,EAAa,GAAM;GACrF,MAAK;GACL,iBAAe;GACf,iBAAe;GACf,iBAAe;GACf,cAAY,OAAO,KAAU,WAAW,IAAQ,KAAA;aAEhD,kBAAC,OAAD;IACE,WAAU;IACV,OAAO;KAAE,OAAO,GAAG,EAAI;KAAI,iBAAiB;KAAW;IACvD,CAAA;GACE,CAAA,CACF"}
1
+ {"version":3,"file":"ProgressMeter.js","names":[],"sources":["../../../../src/assethandler/components/charts/ProgressMeter.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\nimport { toneColor, type MeterTone, type ValueFormatter } from './chartTheme';\n\nexport interface ProgressMeterProps {\n /** Current value. */\n value: number;\n /** Full-scale value. Default 100. */\n max?: number;\n /** Leading caption (e.g. \"Seats used\", \"Budget spent\"). */\n label?: ReactNode;\n /**\n * Severity thresholds as fractions of `max` (0–1). With the default\n * `higherIsWorse` a fraction ≥ `danger` turns the fill red, ≥ `warning` amber.\n * Default `{ warning: 0.75, danger: 0.9 }`.\n */\n thresholds?: { warning: number; danger: number };\n /** Whether a fuller meter is worse (usage/budget, default) or better (progress). */\n higherIsWorse?: boolean;\n /** Force a tone, bypassing thresholds. */\n tone?: MeterTone;\n /** Show the `value / max` readout on the right of the label row. Default true. */\n showValue?: boolean;\n /** Formats the value + max readout. Default grouped integer. */\n format?: ValueFormatter;\n /** Bar thickness. Default `md`. */\n size?: 'sm' | 'md' | 'lg';\n className?: string;\n}\n\nconst TRACK_HEIGHT: Record<NonNullable<ProgressMeterProps['size']>, string> = {\n sm: 'h-1.5',\n md: 'h-2.5',\n lg: 'h-3.5',\n};\n\nconst defaultFormat: ValueFormatter = (value) => value.toLocaleString();\n\n/**\n * ProgressMeter — a linear meter for a single ratio (seat usage, budget spent,\n * progress to target). The fill carries severity (good → warning → danger) via\n * reserved status tokens over a muted track; the width transition is gated\n * behind `motion-safe` so reduced-motion users get an instant fill. Token-only,\n * no raw colour.\n */\nexport function ProgressMeter({\n value,\n max = 100,\n label,\n thresholds = { warning: 0.75, danger: 0.9 },\n higherIsWorse = true,\n tone,\n showValue = true,\n format = defaultFormat,\n size = 'md',\n className,\n}: ProgressMeterProps) {\n const safeMax = max > 0 ? max : 1;\n const fraction = Math.min(1, Math.max(0, value / safeMax));\n const pct = Math.round(fraction * 100);\n\n const resolvedTone: MeterTone =\n tone ??\n (higherIsWorse\n ? fraction >= thresholds.danger\n ? 'danger'\n : fraction >= thresholds.warning\n ? 'warning'\n : 'success'\n : fraction >= thresholds.warning\n ? 'success'\n : fraction >= thresholds.danger\n ? 'warning'\n : 'danger');\n\n const fillColor = toneColor(resolvedTone);\n\n return (\n <div className={cn('w-full', className)}>\n {label !== undefined || showValue ? (\n <div className=\"mb-1.5 flex items-center justify-between gap-3 text-sm\">\n {label !== undefined ? (\n <span className=\"min-w-0 truncate font-medium text-text-primary\">{label}</span>\n ) : (\n <span />\n )}\n {showValue ? (\n <span className=\"shrink-0 tabular-nums text-text-secondary\">\n {format(value)}\n <span className=\"text-text-muted\"> / {format(max)}</span>\n </span>\n ) : null}\n </div>\n ) : null}\n\n <div\n className={cn('w-full overflow-hidden rounded-full bg-bg-sunken', TRACK_HEIGHT[size])}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={typeof label === 'string' ? label : undefined}\n >\n <div\n className=\"h-full rounded-full motion-safe:transition-[width] motion-safe:duration-500\"\n style={{ width: `${pct}%`, backgroundColor: fillColor }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;AA8BA,IAAM,IAAwE;CAC5E,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAEM,KAAiC,MAAU,EAAM,eAAe;AAStE,SAAgB,EAAc,EAC5B,UACA,SAAM,KACN,UACA,gBAAa;CAAE,SAAS;CAAM,QAAQ;AAAI,GAC1C,mBAAgB,IAChB,SACA,eAAY,IACZ,YAAS,GACT,UAAO,MACP,gBACqB;CAErB,IAAM,IAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KADzB,IAAM,IAAI,IAAM,EACwB,CAAC,GACnD,IAAM,KAAK,MAAM,IAAW,GAAG,GAgB/B,IAAY,EAbhB,MACC,IACG,KAAY,EAAW,SACrB,WACA,KAAY,EAAW,UACrB,YACA,YACJ,KAAY,EAAW,UACrB,YACA,KAAY,EAAW,SACrB,YACA,SAE8B;CAExC,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,UAAU,CAAS;YAAtC,CACG,MAAU,KAAA,KAAa,IACtB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,MAAU,KAAA,IAGT,kBAAC,QAAD,CAAO,CAAA,IAFP,kBAAC,QAAD;IAAM,WAAU;cAAkD;GAAY,CAAA,GAI/E,IACC,kBAAC,QAAD;IAAM,WAAU;cAAhB,CACG,EAAO,CAAK,GACb,kBAAC,QAAD;KAAM,WAAU;eAAhB,CAAkC,OAAI,EAAO,CAAG,CAAQ;MACpD;QACJ,IACD;OACH,MAEJ,kBAAC,OAAD;GACE,WAAW,EAAG,oDAAoD,EAAa,EAAK;GACpF,MAAK;GACL,iBAAe;GACf,iBAAe;GACf,iBAAe;GACf,cAAY,OAAO,KAAU,WAAW,IAAQ,KAAA;aAEhD,kBAAC,OAAD;IACE,WAAU;IACV,OAAO;KAAE,OAAO,GAAG,EAAI;KAAI,iBAAiB;IAAU;GACvD,CAAA;EACE,CAAA,CACF;;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"RadialGauge.js","names":[],"sources":["../../../../src/assethandler/components/charts/RadialGauge.tsx"],"sourcesContent":["import { PolarAngleAxis, RadialBar, RadialBarChart, ResponsiveContainer } from 'recharts';\nimport { cn } from '../../utils/cn';\nimport {\n chartTokens,\n toneColor,\n usePrefersReducedMotion,\n type MeterTone,\n type ValueFormatter,\n} from './chartTheme';\n\nexport interface RadialGaugeProps {\n /** The measured value. */\n value: number;\n /** Scale minimum. Default 0. */\n min?: number;\n /** Scale maximum. Default 100. */\n max?: number;\n /** Big centre caption (e.g. \"Compliance\"). */\n label?: string;\n /** Small caption under the value. */\n sublabel?: string;\n /**\n * Severity thresholds in value units. With `higherIsBetter` (default) pass\n * `warning > danger` (e.g. `{ warning: 80, danger: 50 }` → ≥80 good, 50–79\n * warning, <50 danger). Defaults derive from the range.\n */\n thresholds?: { warning: number; danger: number };\n /** Whether a higher value is better (compliance/health) or worse (risk). Default true. */\n higherIsBetter?: boolean;\n /** Force a tone, bypassing threshold logic. */\n tone?: MeterTone;\n /** Force an explicit colour, bypassing tone + thresholds. */\n color?: string;\n /** Pixel height. Default 200. */\n height?: number;\n /** Formats the centre value. Default rounds to an integer. */\n format?: ValueFormatter;\n /** Accessible name. Default derived from label + value. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.min(max, Math.max(min, value));\n\n/**\n * RadialGauge — a single value on a 270° arc (compliance score, asset health,\n * risk). The arc colour follows severity thresholds (good → warning → danger)\n * using reserved status tokens, over a muted track. Center shows the value and\n * label; respects `prefers-reduced-motion`.\n */\nexport function RadialGauge({\n value,\n min = 0,\n max = 100,\n label,\n sublabel,\n thresholds,\n higherIsBetter = true,\n tone,\n color,\n height = 200,\n format = (v) => Math.round(v).toString(),\n ariaLabel,\n className,\n}: RadialGaugeProps) {\n const reducedMotion = usePrefersReducedMotion();\n const range = max - min || 1;\n const clamped = clamp(value, min, max);\n\n const warning = thresholds?.warning ?? (higherIsBetter ? min + range * 0.8 : min + range * 0.5);\n const danger = thresholds?.danger ?? (higherIsBetter ? min + range * 0.5 : min + range * 0.8);\n\n const resolvedTone: MeterTone =\n tone ??\n (higherIsBetter\n ? value >= warning\n ? 'success'\n : value >= danger\n ? 'warning'\n : 'danger'\n : value <= warning\n ? 'success'\n : value <= danger\n ? 'warning'\n : 'danger');\n\n const arcColor = color ?? toneColor(resolvedTone);\n const data = [{ name: label ?? 'value', value: clamped }];\n const accessibleName = ariaLabel ?? `${label ? `${label}: ` : ''}${format(value)}`;\n\n return (\n <figure\n role=\"img\"\n aria-label={accessibleName}\n className={cn('relative w-full', className)}\n style={{ height }}\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RadialBarChart\n data={data}\n innerRadius=\"72%\"\n outerRadius=\"100%\"\n barSize={14}\n startAngle={225}\n endAngle={-45}\n >\n <PolarAngleAxis type=\"number\" domain={[min, max]} angleAxisId={0} tick={false} />\n <RadialBar\n dataKey=\"value\"\n angleAxisId={0}\n background={{ fill: chartTokens.track }}\n cornerRadius={999}\n fill={arcColor}\n isAnimationActive={!reducedMotion}\n />\n </RadialBarChart>\n </ResponsiveContainer>\n\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-3xl font-bold leading-none text-text-primary\">{format(value)}</span>\n {label ? (\n <span className=\"mt-1 text-sm font-medium text-text-secondary\">{label}</span>\n ) : null}\n {sublabel ? <span className=\"text-xs text-text-muted\">{sublabel}</span> : null}\n </div>\n </figure>\n );\n}\n"],"mappings":";;;;;;;;AA0CA,IAAM,KAAS,GAAe,GAAa,MACzC,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,EAAM,CAAC;AAQrC,SAAgB,EAAY,EAC1B,UACA,SAAM,GACN,SAAM,KACN,UACA,aACA,eACA,oBAAiB,IACjB,SACA,UACA,YAAS,KACT,aAAU,MAAM,KAAK,MAAM,EAAE,CAAC,UAAU,EACxC,cACA,gBACmB;CACnB,IAAM,IAAgB,GAAyB,EACzC,IAAQ,IAAM,KAAO,GACrB,IAAU,EAAM,GAAO,GAAK,EAAI,EAEhC,IAAU,GAAY,YAAY,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KACrF,IAAS,GAAY,WAAW,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KAgBnF,IAAW,KAAS,EAbxB,MACC,IACG,KAAS,IACP,YACA,KAAS,IACP,YACA,WACJ,KAAS,IACP,YACA,KAAS,IACP,YACA,UAEuC,EAC3C,IAAO,CAAC;EAAE,MAAM,KAAS;EAAS,OAAO;EAAS,CAAC;AAGzD,QACE,kBAAC,UAAD;EACE,MAAK;EACL,cALmB,KAAa,GAAG,IAAQ,GAAG,EAAM,MAAM,KAAK,EAAO,EAAM;EAM5E,WAAW,EAAG,mBAAmB,EAAU;EAC3C,OAAO,EAAE,WAAQ;YAJnB,CAME,kBAAC,GAAD;GAAqB,OAAM;GAAO,QAAO;aACvC,kBAAC,GAAD;IACQ;IACN,aAAY;IACZ,aAAY;IACZ,SAAS;IACT,YAAY;IACZ,UAAU;cANZ,CAQE,kBAAC,GAAD;KAAgB,MAAK;KAAS,QAAQ,CAAC,GAAK,EAAI;KAAE,aAAa;KAAG,MAAM;KAAS,CAAA,EACjF,kBAAC,GAAD;KACE,SAAQ;KACR,aAAa;KACb,YAAY,EAAE,MAAM,EAAY,OAAO;KACvC,cAAc;KACd,MAAM;KACN,mBAAmB,CAAC;KACpB,CAAA,CACa;;GACG,CAAA,EAEtB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,QAAD;KAAM,WAAU;eAAqD,EAAO,EAAM;KAAQ,CAAA;IACzF,IACC,kBAAC,QAAD;KAAM,WAAU;eAAgD;KAAa,CAAA,GAC3E;IACH,IAAW,kBAAC,QAAD;KAAM,WAAU;eAA2B;KAAgB,CAAA,GAAG;IACtE;KACC"}
1
+ {"version":3,"file":"RadialGauge.js","names":[],"sources":["../../../../src/assethandler/components/charts/RadialGauge.tsx"],"sourcesContent":["import { PolarAngleAxis, RadialBar, RadialBarChart, ResponsiveContainer } from 'recharts';\nimport { cn } from '../../utils/cn';\nimport {\n chartTokens,\n toneColor,\n usePrefersReducedMotion,\n type MeterTone,\n type ValueFormatter,\n} from './chartTheme';\n\nexport interface RadialGaugeProps {\n /** The measured value. */\n value: number;\n /** Scale minimum. Default 0. */\n min?: number;\n /** Scale maximum. Default 100. */\n max?: number;\n /** Big centre caption (e.g. \"Compliance\"). */\n label?: string;\n /** Small caption under the value. */\n sublabel?: string;\n /**\n * Severity thresholds in value units. With `higherIsBetter` (default) pass\n * `warning > danger` (e.g. `{ warning: 80, danger: 50 }` → ≥80 good, 50–79\n * warning, <50 danger). Defaults derive from the range.\n */\n thresholds?: { warning: number; danger: number };\n /** Whether a higher value is better (compliance/health) or worse (risk). Default true. */\n higherIsBetter?: boolean;\n /** Force a tone, bypassing threshold logic. */\n tone?: MeterTone;\n /** Force an explicit colour, bypassing tone + thresholds. */\n color?: string;\n /** Pixel height. Default 200. */\n height?: number;\n /** Formats the centre value. Default rounds to an integer. */\n format?: ValueFormatter;\n /** Accessible name. Default derived from label + value. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.min(max, Math.max(min, value));\n\n/**\n * RadialGauge — a single value on a 270° arc (compliance score, asset health,\n * risk). The arc colour follows severity thresholds (good → warning → danger)\n * using reserved status tokens, over a muted track. Center shows the value and\n * label; respects `prefers-reduced-motion`.\n */\nexport function RadialGauge({\n value,\n min = 0,\n max = 100,\n label,\n sublabel,\n thresholds,\n higherIsBetter = true,\n tone,\n color,\n height = 200,\n format = (v) => Math.round(v).toString(),\n ariaLabel,\n className,\n}: RadialGaugeProps) {\n const reducedMotion = usePrefersReducedMotion();\n const range = max - min || 1;\n const clamped = clamp(value, min, max);\n\n const warning = thresholds?.warning ?? (higherIsBetter ? min + range * 0.8 : min + range * 0.5);\n const danger = thresholds?.danger ?? (higherIsBetter ? min + range * 0.5 : min + range * 0.8);\n\n const resolvedTone: MeterTone =\n tone ??\n (higherIsBetter\n ? value >= warning\n ? 'success'\n : value >= danger\n ? 'warning'\n : 'danger'\n : value <= warning\n ? 'success'\n : value <= danger\n ? 'warning'\n : 'danger');\n\n const arcColor = color ?? toneColor(resolvedTone);\n const data = [{ name: label ?? 'value', value: clamped }];\n const accessibleName = ariaLabel ?? `${label ? `${label}: ` : ''}${format(value)}`;\n\n return (\n <figure\n role=\"img\"\n aria-label={accessibleName}\n className={cn('relative w-full', className)}\n style={{ height }}\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RadialBarChart\n data={data}\n innerRadius=\"72%\"\n outerRadius=\"100%\"\n barSize={14}\n startAngle={225}\n endAngle={-45}\n >\n <PolarAngleAxis type=\"number\" domain={[min, max]} angleAxisId={0} tick={false} />\n <RadialBar\n dataKey=\"value\"\n angleAxisId={0}\n background={{ fill: chartTokens.track }}\n cornerRadius={999}\n fill={arcColor}\n isAnimationActive={!reducedMotion}\n />\n </RadialBarChart>\n </ResponsiveContainer>\n\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-3xl font-bold leading-none text-text-primary\">{format(value)}</span>\n {label ? (\n <span className=\"mt-1 text-sm font-medium text-text-secondary\">{label}</span>\n ) : null}\n {sublabel ? <span className=\"text-xs text-text-muted\">{sublabel}</span> : null}\n </div>\n </figure>\n );\n}\n"],"mappings":";;;;;;;;AA0CA,IAAM,KAAS,GAAe,GAAa,MACzC,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,CAAK,CAAC;AAQpC,SAAgB,EAAY,EAC1B,UACA,SAAM,GACN,SAAM,KACN,UACA,aACA,eACA,oBAAiB,IACjB,SACA,UACA,YAAS,KACT,aAAU,MAAM,KAAK,MAAM,CAAC,EAAE,SAAS,GACvC,cACA,gBACmB;CACnB,IAAM,IAAgB,EAAwB,GACxC,IAAQ,IAAM,KAAO,GACrB,IAAU,EAAM,GAAO,GAAK,CAAG,GAE/B,IAAU,GAAY,YAAY,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KACrF,IAAS,GAAY,WAAW,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KAgBnF,IAAW,KAAS,EAbxB,MACC,IACG,KAAS,IACP,YACA,KAAS,IACP,YACA,WACJ,KAAS,IACP,YACA,KAAS,IACP,YACA,SAEsC,GAC1C,IAAO,CAAC;EAAE,MAAM,KAAS;EAAS,OAAO;CAAQ,CAAC;CAGxD,OACE,kBAAC,UAAD;EACE,MAAK;EACL,cALmB,KAAa,GAAG,IAAQ,GAAG,EAAM,MAAM,KAAK,EAAO,CAAK;EAM3E,WAAW,EAAG,mBAAmB,CAAS;EAC1C,OAAO,EAAE,UAAO;YAJlB,CAME,kBAAC,GAAD;GAAqB,OAAM;GAAO,QAAO;aACvC,kBAAC,GAAD;IACQ;IACN,aAAY;IACZ,aAAY;IACZ,SAAS;IACT,YAAY;IACZ,UAAU;cANZ,CAQE,kBAAC,GAAD;KAAgB,MAAK;KAAS,QAAQ,CAAC,GAAK,CAAG;KAAG,aAAa;KAAG,MAAM;IAAQ,CAAA,GAChF,kBAAC,GAAD;KACE,SAAQ;KACR,aAAa;KACb,YAAY,EAAE,MAAM,EAAY,MAAM;KACtC,cAAc;KACd,MAAM;KACN,mBAAmB,CAAC;IACrB,CAAA,CACa;;EACG,CAAA,GAErB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,QAAD;KAAM,WAAU;eAAqD,EAAO,CAAK;IAAQ,CAAA;IACxF,IACC,kBAAC,QAAD;KAAM,WAAU;eAAgD;IAAY,CAAA,IAC1E;IACH,IAAW,kBAAC,QAAD;KAAM,WAAU;eAA2B;IAAe,CAAA,IAAI;GACvE;IACC;;AAEZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sparkline.js","names":[],"sources":["../../../../src/assethandler/components/charts/Sparkline.tsx"],"sourcesContent":["import { useId } from 'react';\nimport {\n Area,\n AreaChart,\n Line,\n LineChart,\n ReferenceDot,\n ResponsiveContainer,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { cn } from '../../utils/cn';\nimport { chartTokens, usePrefersReducedMotion } from './chartTheme';\n\nexport interface SparklineProps {\n /** The series, oldest → newest. */\n data: number[];\n /** Line or gradient-filled area. Default `area`. */\n type?: 'line' | 'area';\n /** Mark colour (a CSS colour, default the amber brand token). */\n color?: string;\n /** Pixel height. Default 40. */\n height?: number;\n /** Stroke width. Default 2. */\n strokeWidth?: number;\n /** Emphasise the final point with a ringed dot. Default true. */\n showEndDot?: boolean;\n className?: string;\n /** Accessible name; when omitted the sparkline is decorative (`aria-hidden`). */\n ariaLabel?: string;\n}\n\ninterface SparkPoint {\n i: number;\n v: number;\n}\n\n/**\n * Sparkline — a tiny, axis-less trend line/area for KPI tiles. Reads its colour\n * from a live token (brand amber by default) so it recolours with the theme,\n * respects `prefers-reduced-motion`, and shows a stable muted baseline instead\n * of fabricating a shape when there is too little data.\n */\nexport function Sparkline({\n data,\n type = 'area',\n color = chartTokens.brand,\n height = 40,\n strokeWidth = 2,\n showEndDot = true,\n className,\n ariaLabel,\n}: SparklineProps) {\n const gradientId = useId();\n const reducedMotion = usePrefersReducedMotion();\n\n const points: SparkPoint[] = data\n .filter((value) => typeof value === 'number' && Number.isFinite(value))\n .map((value, index) => ({ i: index, v: value }));\n\n const decorative = ariaLabel === undefined;\n\n if (points.length < 2) {\n return (\n <div\n className={cn('flex items-center', className)}\n style={{ height }}\n aria-hidden={decorative ? true : undefined}\n aria-label={decorative ? undefined : ariaLabel}\n role={decorative ? undefined : 'img'}\n >\n <span className=\"h-px w-full bg-border-seam\" />\n </div>\n );\n }\n\n const values = points.map((p) => p.v);\n const min = Math.min(...values);\n const max = Math.max(...values);\n const pad = (max - min || Math.abs(max) || 1) * 0.15;\n const last = points[points.length - 1];\n\n return (\n <div\n className={cn('w-full', className)}\n style={{ height }}\n role={decorative ? undefined : 'img'}\n aria-hidden={decorative ? true : undefined}\n aria-label={decorative ? undefined : ariaLabel}\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {type === 'area' ? (\n <AreaChart data={points} margin={{ top: 4, right: 6, bottom: 4, left: 6 }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity={0.28} />\n <stop offset=\"100%\" stopColor={color} stopOpacity={0.02} />\n </linearGradient>\n </defs>\n <XAxis dataKey=\"i\" type=\"number\" hide domain={['dataMin', 'dataMax']} />\n <YAxis hide domain={[min - pad, max + pad]} />\n <Area\n type=\"monotone\"\n dataKey=\"v\"\n stroke={color}\n strokeWidth={strokeWidth}\n fill={`url(#${gradientId})`}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={false}\n />\n {showEndDot ? (\n <ReferenceDot\n x={last.i}\n y={last.v}\n r={3.5}\n fill={color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n ) : null}\n </AreaChart>\n ) : (\n <LineChart data={points} margin={{ top: 4, right: 6, bottom: 4, left: 6 }}>\n <XAxis dataKey=\"i\" type=\"number\" hide domain={['dataMin', 'dataMax']} />\n <YAxis hide domain={[min - pad, max + pad]} />\n <Line\n type=\"monotone\"\n dataKey=\"v\"\n stroke={color}\n strokeWidth={strokeWidth}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={false}\n />\n {showEndDot ? (\n <ReferenceDot\n x={last.i}\n y={last.v}\n r={3.5}\n fill={color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n ) : null}\n </LineChart>\n )}\n </ResponsiveContainer>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Sparkline.js","names":[],"sources":["../../../../src/assethandler/components/charts/Sparkline.tsx"],"sourcesContent":["import { useId } from 'react';\nimport {\n Area,\n AreaChart,\n Line,\n LineChart,\n ReferenceDot,\n ResponsiveContainer,\n XAxis,\n YAxis,\n} from 'recharts';\nimport { cn } from '../../utils/cn';\nimport { chartTokens, usePrefersReducedMotion } from './chartTheme';\n\nexport interface SparklineProps {\n /** The series, oldest → newest. */\n data: number[];\n /** Line or gradient-filled area. Default `area`. */\n type?: 'line' | 'area';\n /** Mark colour (a CSS colour, default the amber brand token). */\n color?: string;\n /** Pixel height. Default 40. */\n height?: number;\n /** Stroke width. Default 2. */\n strokeWidth?: number;\n /** Emphasise the final point with a ringed dot. Default true. */\n showEndDot?: boolean;\n className?: string;\n /** Accessible name; when omitted the sparkline is decorative (`aria-hidden`). */\n ariaLabel?: string;\n}\n\ninterface SparkPoint {\n i: number;\n v: number;\n}\n\n/**\n * Sparkline — a tiny, axis-less trend line/area for KPI tiles. Reads its colour\n * from a live token (brand amber by default) so it recolours with the theme,\n * respects `prefers-reduced-motion`, and shows a stable muted baseline instead\n * of fabricating a shape when there is too little data.\n */\nexport function Sparkline({\n data,\n type = 'area',\n color = chartTokens.brand,\n height = 40,\n strokeWidth = 2,\n showEndDot = true,\n className,\n ariaLabel,\n}: SparklineProps) {\n const gradientId = useId();\n const reducedMotion = usePrefersReducedMotion();\n\n const points: SparkPoint[] = data\n .filter((value) => typeof value === 'number' && Number.isFinite(value))\n .map((value, index) => ({ i: index, v: value }));\n\n const decorative = ariaLabel === undefined;\n\n if (points.length < 2) {\n return (\n <div\n className={cn('flex items-center', className)}\n style={{ height }}\n aria-hidden={decorative ? true : undefined}\n aria-label={decorative ? undefined : ariaLabel}\n role={decorative ? undefined : 'img'}\n >\n <span className=\"h-px w-full bg-border-seam\" />\n </div>\n );\n }\n\n const values = points.map((p) => p.v);\n const min = Math.min(...values);\n const max = Math.max(...values);\n const pad = (max - min || Math.abs(max) || 1) * 0.15;\n const last = points[points.length - 1];\n\n return (\n <div\n className={cn('w-full', className)}\n style={{ height }}\n role={decorative ? undefined : 'img'}\n aria-hidden={decorative ? true : undefined}\n aria-label={decorative ? undefined : ariaLabel}\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {type === 'area' ? (\n <AreaChart data={points} margin={{ top: 4, right: 6, bottom: 4, left: 6 }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity={0.28} />\n <stop offset=\"100%\" stopColor={color} stopOpacity={0.02} />\n </linearGradient>\n </defs>\n <XAxis dataKey=\"i\" type=\"number\" hide domain={['dataMin', 'dataMax']} />\n <YAxis hide domain={[min - pad, max + pad]} />\n <Area\n type=\"monotone\"\n dataKey=\"v\"\n stroke={color}\n strokeWidth={strokeWidth}\n fill={`url(#${gradientId})`}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={false}\n />\n {showEndDot ? (\n <ReferenceDot\n x={last.i}\n y={last.v}\n r={3.5}\n fill={color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n ) : null}\n </AreaChart>\n ) : (\n <LineChart data={points} margin={{ top: 4, right: 6, bottom: 4, left: 6 }}>\n <XAxis dataKey=\"i\" type=\"number\" hide domain={['dataMin', 'dataMax']} />\n <YAxis hide domain={[min - pad, max + pad]} />\n <Line\n type=\"monotone\"\n dataKey=\"v\"\n stroke={color}\n strokeWidth={strokeWidth}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={false}\n />\n {showEndDot ? (\n <ReferenceDot\n x={last.i}\n y={last.v}\n r={3.5}\n fill={color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n ) : null}\n </LineChart>\n )}\n </ResponsiveContainer>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TrendChart.js","names":[],"sources":["../../../../src/assethandler/components/charts/TrendChart.tsx"],"sourcesContent":["import { useId } from 'react';\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceDot,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport {\n chartTokens,\n defaultSeriesColor,\n formatNumber,\n usePrefersReducedMotion,\n type ChartDatum,\n type ChartSeries,\n type ValueFormatter,\n} from './chartTheme';\nimport { ChartDataTable, ChartEmpty, ChartFigure, ChartLegend, ChartTooltip } from './ChartParts';\n\nexport interface TrendChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the x-axis category/time value. */\n xKey: string;\n /** One or more numeric series. Single series reads on-brand (amber). */\n series: ChartSeries[];\n /** Line, or gradient-filled area. Default `area`. */\n type?: 'line' | 'area';\n /** Pixel height of the plot. Default 260. */\n height?: number;\n /** Formats y values in the axis and tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats x tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the horizontal grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Emphasise each series' final point with a ringed dot. Default true. */\n showEndDots?: boolean;\n /** Message shown when `data` is empty — never fabricate a shape. */\n emptyLabel?: string;\n /** Accessible name for the figure. Default derived from the series labels. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * TrendChart — value-over-time as a line or gradient area (asset value,\n * emissions, depreciation). Theme-aware tokens, a hairline grid, a crosshair\n * tooltip, emphasised endpoints, a legend for multi-series, an empty state and\n * a screen-reader data table. Respects `prefers-reduced-motion`.\n */\nexport function TrendChart({\n data,\n xKey,\n series,\n type = 'area',\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n showEndDots = true,\n emptyLabel,\n ariaLabel,\n className,\n}: TrendChartProps) {\n const gradientBase = useId();\n const reducedMotion = usePrefersReducedMotion();\n\n const resolved = series.map((s, index) => ({\n ...s,\n label: s.label ?? s.key,\n color: s.color ?? defaultSeriesColor(index, series.length),\n }));\n const label = ariaLabel ?? `Trend of ${resolved.map((s) => s.label).join(', ')}`;\n\n if (data.length === 0) {\n return <ChartEmpty height={height} label={emptyLabel} className={className} />;\n }\n\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n\n const lastFiniteIndex = (key: string): number => {\n for (let i = data.length - 1; i >= 0; i -= 1) {\n const value = data[i][key];\n if (typeof value === 'number' && Number.isFinite(value)) return i;\n }\n return -1;\n };\n\n const Chart = type === 'area' ? AreaChart : LineChart;\n\n return (\n <ChartFigure\n ariaLabel={label}\n height={height}\n className={className}\n a11y={\n <ChartDataTable\n caption={label}\n xLabel={xKey}\n xKey={xKey}\n data={data}\n series={resolved}\n valueFormat={valueFormat}\n />\n }\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <Chart data={data} margin={{ top: 12, right: 16, bottom: 4, left: 4 }}>\n <defs>\n {resolved.map((s, index) => (\n <linearGradient\n key={s.key}\n id={`${gradientBase}-${index}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"0%\" stopColor={s.color} stopOpacity={0.24} />\n <stop offset=\"95%\" stopColor={s.color} stopOpacity={0.02} />\n </linearGradient>\n ))}\n </defs>\n\n {showGrid ? (\n <CartesianGrid vertical={false} stroke={chartTokens.grid} strokeWidth={1} />\n ) : null}\n\n <XAxis\n dataKey={xKey}\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n minTickGap={16}\n tickFormatter={\n xTickFormat ? (value) => xTickFormat(value as string | number) : undefined\n }\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n\n <Tooltip\n cursor={{ stroke: chartTokens.axis, strokeWidth: 1 }}\n content={\n <ChartTooltip valueFormat={valueFormat} labelFormat={xTickFormat} hideLabel={false} />\n }\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) =>\n type === 'area' ? (\n <Area\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n fill={`url(#${gradientBase}-${index})`}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: chartTokens.surface, fill: s.color }}\n />\n ) : (\n <Line\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: chartTokens.surface, fill: s.color }}\n />\n )\n )}\n\n {showEndDots\n ? resolved.map((s) => {\n const index = lastFiniteIndex(s.key);\n if (index < 0) return null;\n return (\n <ReferenceDot\n key={`end-${s.key}`}\n x={data[index][xKey] as string | number}\n y={data[index][s.key] as number}\n r={4}\n fill={s.color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n );\n })\n : null}\n </Chart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TrendChart.js","names":[],"sources":["../../../../src/assethandler/components/charts/TrendChart.tsx"],"sourcesContent":["import { useId } from 'react';\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceDot,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts';\nimport {\n chartTokens,\n defaultSeriesColor,\n formatNumber,\n usePrefersReducedMotion,\n type ChartDatum,\n type ChartSeries,\n type ValueFormatter,\n} from './chartTheme';\nimport { ChartDataTable, ChartEmpty, ChartFigure, ChartLegend, ChartTooltip } from './ChartParts';\n\nexport interface TrendChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the x-axis category/time value. */\n xKey: string;\n /** One or more numeric series. Single series reads on-brand (amber). */\n series: ChartSeries[];\n /** Line, or gradient-filled area. Default `area`. */\n type?: 'line' | 'area';\n /** Pixel height of the plot. Default 260. */\n height?: number;\n /** Formats y values in the axis and tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats x tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the horizontal grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Emphasise each series' final point with a ringed dot. Default true. */\n showEndDots?: boolean;\n /** Message shown when `data` is empty — never fabricate a shape. */\n emptyLabel?: string;\n /** Accessible name for the figure. Default derived from the series labels. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * TrendChart — value-over-time as a line or gradient area (asset value,\n * emissions, depreciation). Theme-aware tokens, a hairline grid, a crosshair\n * tooltip, emphasised endpoints, a legend for multi-series, an empty state and\n * a screen-reader data table. Respects `prefers-reduced-motion`.\n */\nexport function TrendChart({\n data,\n xKey,\n series,\n type = 'area',\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n showEndDots = true,\n emptyLabel,\n ariaLabel,\n className,\n}: TrendChartProps) {\n const gradientBase = useId();\n const reducedMotion = usePrefersReducedMotion();\n\n const resolved = series.map((s, index) => ({\n ...s,\n label: s.label ?? s.key,\n color: s.color ?? defaultSeriesColor(index, series.length),\n }));\n const label = ariaLabel ?? `Trend of ${resolved.map((s) => s.label).join(', ')}`;\n\n if (data.length === 0) {\n return <ChartEmpty height={height} label={emptyLabel} className={className} />;\n }\n\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n\n const lastFiniteIndex = (key: string): number => {\n for (let i = data.length - 1; i >= 0; i -= 1) {\n const value = data[i][key];\n if (typeof value === 'number' && Number.isFinite(value)) return i;\n }\n return -1;\n };\n\n const Chart = type === 'area' ? AreaChart : LineChart;\n\n return (\n <ChartFigure\n ariaLabel={label}\n height={height}\n className={className}\n a11y={\n <ChartDataTable\n caption={label}\n xLabel={xKey}\n xKey={xKey}\n data={data}\n series={resolved}\n valueFormat={valueFormat}\n />\n }\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <Chart data={data} margin={{ top: 12, right: 16, bottom: 4, left: 4 }}>\n <defs>\n {resolved.map((s, index) => (\n <linearGradient\n key={s.key}\n id={`${gradientBase}-${index}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"0%\" stopColor={s.color} stopOpacity={0.24} />\n <stop offset=\"95%\" stopColor={s.color} stopOpacity={0.02} />\n </linearGradient>\n ))}\n </defs>\n\n {showGrid ? (\n <CartesianGrid vertical={false} stroke={chartTokens.grid} strokeWidth={1} />\n ) : null}\n\n <XAxis\n dataKey={xKey}\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n minTickGap={16}\n tickFormatter={\n xTickFormat ? (value) => xTickFormat(value as string | number) : undefined\n }\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n\n <Tooltip\n cursor={{ stroke: chartTokens.axis, strokeWidth: 1 }}\n content={\n <ChartTooltip valueFormat={valueFormat} labelFormat={xTickFormat} hideLabel={false} />\n }\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) =>\n type === 'area' ? (\n <Area\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n fill={`url(#${gradientBase}-${index})`}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: chartTokens.surface, fill: s.color }}\n />\n ) : (\n <Line\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{ r: 4, strokeWidth: 2, stroke: chartTokens.surface, fill: s.color }}\n />\n )\n )}\n\n {showEndDots\n ? resolved.map((s) => {\n const index = lastFiniteIndex(s.key);\n if (index < 0) return null;\n return (\n <ReferenceDot\n key={`end-${s.key}`}\n x={data[index][xKey] as string | number}\n y={data[index][s.key] as number}\n r={4}\n fill={s.color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n );\n })\n : null}\n </Chart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"chartTheme.js","names":[],"sources":["../../../../src/assethandler/components/charts/chartTheme.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\n/**\n * chartTheme — the single source of truth that maps every chart mark to a live\n * semantic CSS custom property from the Boff UI 2.0 design system\n * (`@burdenoff/fe-libs/shared/tokens`).\n *\n * Because every value is a `var(--color-*)` reference rather than a baked hex,\n * the charts are theme-aware for free: they recolour instantly on a light/dark\n * switch and pick up the AssetHandler amber brand (which the host shell writes\n * into `--color-accent-primary`) with zero JS re-resolution. Nothing here is a\n * raw colour — the design system owns the palette; these components only\n * reference it.\n *\n * Palette provenance: the categorical ramp is the design system's validated\n * 12-step `--color-chart-*` scale. It is CVD-safe (worst adjacent Machado-2009\n * ΔE ≈ 35 in light / ≈ 52 in dark, well above the ≥ 12 target). Slots are\n * assigned in fixed order and NEVER cycled — a series index past the ramp folds\n * onto the last slot rather than repainting an existing hue (see `seriesColor`).\n */\nexport const chartTokens = {\n /** Categorical identity ramp — fixed order, assigned in sequence, never cycled. */\n series: [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n 'var(--color-chart-6)',\n 'var(--color-chart-7)',\n 'var(--color-chart-8)',\n 'var(--color-chart-9)',\n 'var(--color-chart-10)',\n 'var(--color-chart-11)',\n 'var(--color-chart-12)',\n ],\n /** Brand accent (amber for AssetHandler) — the default for a single series. */\n brand: 'var(--color-accent-primary)',\n /** Value polarity. */\n positive: 'var(--color-chart-positive)',\n negative: 'var(--color-chart-negative)',\n /** Reserved status scale — always paired with an icon + label at the call site. */\n status: {\n success: 'var(--color-status-success-bg)',\n warning: 'var(--color-status-warning-bg)',\n danger: 'var(--color-status-error-bg)',\n info: 'var(--color-status-info-bg)',\n },\n /** Recessive chrome. */\n grid: 'var(--color-chart-grid)',\n axis: 'var(--color-chart-axis)',\n surface: 'var(--color-bg-surface)',\n track: 'var(--color-bg-sunken)',\n border: 'var(--color-border-seam)',\n /** Ink — marks never wear these; labels, axes and legends do. */\n textPrimary: 'var(--color-text-primary)',\n textSecondary: 'var(--color-text-secondary)',\n textMuted: 'var(--color-text-muted)',\n} as const;\n\n/** A named data series drawn by TrendChart / BarsChart. */\nexport interface ChartSeries {\n /** Key into each datum object. */\n key: string;\n /** Human label (legend + tooltip). Falls back to `key`. */\n label?: string;\n /** Explicit mark colour (a CSS colour, typically a `var(--color-*)`). */\n color?: string;\n}\n\n/** A single datum row: an x-value plus one or more numeric series values. */\nexport type ChartDatum = Record<string, string | number | null | undefined>;\n\n/** A slice for DonutChart. */\nexport interface DonutSlice {\n name: string;\n value: number;\n color?: string;\n}\n\n/** Severity tone shared by meters and gauges. */\nexport type MeterTone = 'success' | 'warning' | 'danger';\n\n/**\n * Pick the categorical hue for slot `i`, clamped to the ramp — it NEVER cycles.\n * A count beyond the ramp folds onto the last slot (callers that need more\n * distinct categories should aggregate the tail into \"Other\").\n */\nexport function seriesColor(i: number): string {\n const ramp = chartTokens.series;\n if (i <= 0) return ramp[0];\n return i < ramp.length ? ramp[i] : ramp[ramp.length - 1];\n}\n\n/** Resolve a severity tone to its reserved status token. */\nexport function toneColor(tone: MeterTone): string {\n return chartTokens.status[tone];\n}\n\n/**\n * Resolve the default colour for series slot `i` in an N-series chart: a single\n * series reads on-brand (amber); multiple series take the categorical ramp.\n */\nexport function defaultSeriesColor(index: number, total: number): string {\n return total <= 1 ? chartTokens.brand : seriesColor(index);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Number formatting */\n/* -------------------------------------------------------------------------- */\n\n/** A value formatter: `(value) => label`. Passed to every chart's `valueFormat`. */\nexport type ValueFormatter = (value: number) => string;\n\n/** Plain grouped integer/decimal, e.g. `17,960`. Default everywhere. */\nexport const formatNumber: ValueFormatter = (value) => value.toLocaleString();\n\n/** Compact notation, e.g. `12.9K`, `4.2M` — for axis ticks and dense KPIs. */\nexport const formatCompact: ValueFormatter = (value) =>\n new Intl.NumberFormat(undefined, { notation: 'compact', maximumFractionDigits: 1 }).format(value);\n\n/** Compact currency, e.g. `$4.2M`. */\nexport function formatCurrencyCompact(currency = 'USD'): ValueFormatter {\n return (value) =>\n new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(value);\n}\n\n/** Percent with a fixed number of fraction digits, e.g. `68%`. */\nexport function formatPercent(fractionDigits = 0): ValueFormatter {\n return (value) => `${value.toFixed(fractionDigits)}%`;\n}\n\n/** Render an unknown cell value through a formatter, tolerant of strings/null. */\nexport function renderValue(\n value: number | string | null | undefined,\n formatter: ValueFormatter = formatNumber\n): string {\n if (value === null || value === undefined) return '—';\n if (typeof value === 'number') return Number.isFinite(value) ? formatter(value) : '—';\n return String(value);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Motion */\n/* -------------------------------------------------------------------------- */\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction subscribeReducedMotion(onChange: () => void): () => void {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return () => {};\n }\n const query = window.matchMedia(REDUCED_MOTION_QUERY);\n query.addEventListener('change', onChange);\n return () => query.removeEventListener('change', onChange);\n}\n\nfunction getReducedMotionSnapshot(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n\n/**\n * Tracks the user's `prefers-reduced-motion` setting so charts can disable\n * recharts' enter animation. Subscribes to the media query via\n * `useSyncExternalStore` (SSR-safe — defaults to \"not reduced\" on the server).\n */\nexport function usePrefersReducedMotion(): boolean {\n return useSyncExternalStore(subscribeReducedMotion, getReducedMotionSnapshot, () => false);\n}\n"],"mappings":";;AAoBA,IAAa,IAAc;CAEzB,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CAED,OAAO;CAEP,UAAU;CACV,UAAU;CAEV,QAAQ;EACN,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;EACP;CAED,MAAM;CACN,MAAM;CACN,SAAS;CACT,OAAO;CACP,QAAQ;CAER,aAAa;CACb,eAAe;CACf,WAAW;CACZ;AA8BD,SAAgB,EAAY,GAAmB;CAC7C,IAAM,IAAO,EAAY;AAEzB,QADI,KAAK,IAAU,EAAK,KACjB,IAAI,EAAK,SAAS,EAAK,KAAK,EAAK,EAAK,SAAS;;AAIxD,SAAgB,EAAU,GAAyB;AACjD,QAAO,EAAY,OAAO;;AAO5B,SAAgB,EAAmB,GAAe,GAAuB;AACvE,QAAO,KAAS,IAAI,EAAY,QAAQ,EAAY,EAAM;;AAW5D,IAAa,KAAgC,MAAU,EAAM,gBAAgB,EAGhE,KAAiC,MAC5C,IAAI,KAAK,aAAa,KAAA,GAAW;CAAE,UAAU;CAAW,uBAAuB;CAAG,CAAC,CAAC,OAAO,EAAM;AAGnG,SAAgB,EAAsB,IAAW,OAAuB;AACtE,SAAQ,MACN,IAAI,KAAK,aAAa,KAAA,GAAW;EAC/B,OAAO;EACP;EACA,UAAU;EACV,uBAAuB;EACxB,CAAC,CAAC,OAAO,EAAM;;AASpB,SAAgB,EACd,GACA,IAA4B,GACpB;AAGR,QAFI,KAAU,OAAoC,MAC9C,OAAO,KAAU,WAAiB,OAAO,SAAS,EAAM,GAAG,EAAU,EAAM,GAAG,MAC3E,OAAO,EAAM;;AAOtB,IAAM,IAAuB;AAE7B,SAAS,EAAuB,GAAkC;AAChE,KAAI,OAAO,SAAW,OAAe,OAAO,OAAO,cAAe,WAChE,cAAa;CAEf,IAAM,IAAQ,OAAO,WAAW,EAAqB;AAErD,QADA,EAAM,iBAAiB,UAAU,EAAS,QAC7B,EAAM,oBAAoB,UAAU,EAAS;;AAG5D,SAAS,IAAoC;AAE3C,QADI,OAAO,SAAW,OAAe,OAAO,OAAO,cAAe,aAAmB,KAC9E,OAAO,WAAW,EAAqB,CAAC;;AAQjD,SAAgB,IAAmC;AACjD,QAAO,EAAqB,GAAwB,SAAgC,GAAM"}
1
+ {"version":3,"file":"chartTheme.js","names":[],"sources":["../../../../src/assethandler/components/charts/chartTheme.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\n/**\n * chartTheme — the single source of truth that maps every chart mark to a live\n * semantic CSS custom property from the Boff UI 2.0 design system\n * (`@burdenoff/fe-libs/shared/tokens`).\n *\n * Because every value is a `var(--color-*)` reference rather than a baked hex,\n * the charts are theme-aware for free: they recolour instantly on a light/dark\n * switch and pick up the AssetHandler amber brand (which the host shell writes\n * into `--color-accent-primary`) with zero JS re-resolution. Nothing here is a\n * raw colour — the design system owns the palette; these components only\n * reference it.\n *\n * Palette provenance: the categorical ramp is the design system's validated\n * 12-step `--color-chart-*` scale. It is CVD-safe (worst adjacent Machado-2009\n * ΔE ≈ 35 in light / ≈ 52 in dark, well above the ≥ 12 target). Slots are\n * assigned in fixed order and NEVER cycled — a series index past the ramp folds\n * onto the last slot rather than repainting an existing hue (see `seriesColor`).\n */\nexport const chartTokens = {\n /** Categorical identity ramp — fixed order, assigned in sequence, never cycled. */\n series: [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n 'var(--color-chart-6)',\n 'var(--color-chart-7)',\n 'var(--color-chart-8)',\n 'var(--color-chart-9)',\n 'var(--color-chart-10)',\n 'var(--color-chart-11)',\n 'var(--color-chart-12)',\n ],\n /** Brand accent (amber for AssetHandler) — the default for a single series. */\n brand: 'var(--color-accent-primary)',\n /** Value polarity. */\n positive: 'var(--color-chart-positive)',\n negative: 'var(--color-chart-negative)',\n /** Reserved status scale — always paired with an icon + label at the call site. */\n status: {\n success: 'var(--color-status-success-bg)',\n warning: 'var(--color-status-warning-bg)',\n danger: 'var(--color-status-error-bg)',\n info: 'var(--color-status-info-bg)',\n },\n /** Recessive chrome. */\n grid: 'var(--color-chart-grid)',\n axis: 'var(--color-chart-axis)',\n surface: 'var(--color-bg-surface)',\n track: 'var(--color-bg-sunken)',\n border: 'var(--color-border-seam)',\n /** Ink — marks never wear these; labels, axes and legends do. */\n textPrimary: 'var(--color-text-primary)',\n textSecondary: 'var(--color-text-secondary)',\n textMuted: 'var(--color-text-muted)',\n} as const;\n\n/** A named data series drawn by TrendChart / BarsChart. */\nexport interface ChartSeries {\n /** Key into each datum object. */\n key: string;\n /** Human label (legend + tooltip). Falls back to `key`. */\n label?: string;\n /** Explicit mark colour (a CSS colour, typically a `var(--color-*)`). */\n color?: string;\n}\n\n/** A single datum row: an x-value plus one or more numeric series values. */\nexport type ChartDatum = Record<string, string | number | null | undefined>;\n\n/** A slice for DonutChart. */\nexport interface DonutSlice {\n name: string;\n value: number;\n color?: string;\n}\n\n/** Severity tone shared by meters and gauges. */\nexport type MeterTone = 'success' | 'warning' | 'danger';\n\n/**\n * Pick the categorical hue for slot `i`, clamped to the ramp — it NEVER cycles.\n * A count beyond the ramp folds onto the last slot (callers that need more\n * distinct categories should aggregate the tail into \"Other\").\n */\nexport function seriesColor(i: number): string {\n const ramp = chartTokens.series;\n if (i <= 0) return ramp[0];\n return i < ramp.length ? ramp[i] : ramp[ramp.length - 1];\n}\n\n/** Resolve a severity tone to its reserved status token. */\nexport function toneColor(tone: MeterTone): string {\n return chartTokens.status[tone];\n}\n\n/**\n * Resolve the default colour for series slot `i` in an N-series chart: a single\n * series reads on-brand (amber); multiple series take the categorical ramp.\n */\nexport function defaultSeriesColor(index: number, total: number): string {\n return total <= 1 ? chartTokens.brand : seriesColor(index);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Number formatting */\n/* -------------------------------------------------------------------------- */\n\n/** A value formatter: `(value) => label`. Passed to every chart's `valueFormat`. */\nexport type ValueFormatter = (value: number) => string;\n\n/** Plain grouped integer/decimal, e.g. `17,960`. Default everywhere. */\nexport const formatNumber: ValueFormatter = (value) => value.toLocaleString();\n\n/** Compact notation, e.g. `12.9K`, `4.2M` — for axis ticks and dense KPIs. */\nexport const formatCompact: ValueFormatter = (value) =>\n new Intl.NumberFormat(undefined, { notation: 'compact', maximumFractionDigits: 1 }).format(value);\n\n/** Compact currency, e.g. `$4.2M`. */\nexport function formatCurrencyCompact(currency = 'USD'): ValueFormatter {\n return (value) =>\n new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(value);\n}\n\n/** Percent with a fixed number of fraction digits, e.g. `68%`. */\nexport function formatPercent(fractionDigits = 0): ValueFormatter {\n return (value) => `${value.toFixed(fractionDigits)}%`;\n}\n\n/** Render an unknown cell value through a formatter, tolerant of strings/null. */\nexport function renderValue(\n value: number | string | null | undefined,\n formatter: ValueFormatter = formatNumber\n): string {\n if (value === null || value === undefined) return '—';\n if (typeof value === 'number') return Number.isFinite(value) ? formatter(value) : '—';\n return String(value);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Motion */\n/* -------------------------------------------------------------------------- */\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction subscribeReducedMotion(onChange: () => void): () => void {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return () => {};\n }\n const query = window.matchMedia(REDUCED_MOTION_QUERY);\n query.addEventListener('change', onChange);\n return () => query.removeEventListener('change', onChange);\n}\n\nfunction getReducedMotionSnapshot(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n\n/**\n * Tracks the user's `prefers-reduced-motion` setting so charts can disable\n * recharts' enter animation. Subscribes to the media query via\n * `useSyncExternalStore` (SSR-safe — defaults to \"not reduced\" on the server).\n */\nexport function usePrefersReducedMotion(): boolean {\n return useSyncExternalStore(subscribeReducedMotion, getReducedMotionSnapshot, () => false);\n}\n"],"mappings":";;AAoBA,IAAa,IAAc;CAEzB,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAEA,OAAO;CAEP,UAAU;CACV,UAAU;CAEV,QAAQ;EACN,SAAS;EACT,SAAS;EACT,QAAQ;EACR,MAAM;CACR;CAEA,MAAM;CACN,MAAM;CACN,SAAS;CACT,OAAO;CACP,QAAQ;CAER,aAAa;CACb,eAAe;CACf,WAAW;AACb;AA8BA,SAAgB,EAAY,GAAmB;CAC7C,IAAM,IAAO,EAAY;CAEzB,OADI,KAAK,IAAU,EAAK,KACjB,IAAI,EAAK,SAAS,EAAK,KAAK,EAAK,EAAK,SAAS;AACxD;AAGA,SAAgB,EAAU,GAAyB;CACjD,OAAO,EAAY,OAAO;AAC5B;AAMA,SAAgB,EAAmB,GAAe,GAAuB;CACvE,OAAO,KAAS,IAAI,EAAY,QAAQ,EAAY,CAAK;AAC3D;AAUA,IAAa,KAAgC,MAAU,EAAM,eAAe,GAG/D,KAAiC,MAC5C,IAAI,KAAK,aAAa,KAAA,GAAW;CAAE,UAAU;CAAW,uBAAuB;AAAE,CAAC,EAAE,OAAO,CAAK;AAGlG,SAAgB,EAAsB,IAAW,OAAuB;CACtE,QAAQ,MACN,IAAI,KAAK,aAAa,KAAA,GAAW;EAC/B,OAAO;EACP;EACA,UAAU;EACV,uBAAuB;CACzB,CAAC,EAAE,OAAO,CAAK;AACnB;AAQA,SAAgB,EACd,GACA,IAA4B,GACpB;CAGR,OAFI,KAAU,OAAoC,MAC9C,OAAO,KAAU,WAAiB,OAAO,SAAS,CAAK,IAAI,EAAU,CAAK,IAAI,MAC3E,OAAO,CAAK;AACrB;AAMA,IAAM,IAAuB;AAE7B,SAAS,EAAuB,GAAkC;CAChE,IAAI,OAAO,SAAW,OAAe,OAAO,OAAO,cAAe,YAChE,aAAa,CAAC;CAEhB,IAAM,IAAQ,OAAO,WAAW,CAAoB;CAEpD,OADA,EAAM,iBAAiB,UAAU,CAAQ,SAC5B,EAAM,oBAAoB,UAAU,CAAQ;AAC3D;AAEA,SAAS,IAAoC;CAE3C,OADI,OAAO,SAAW,OAAe,OAAO,OAAO,cAAe,aAAmB,KAC9E,OAAO,WAAW,CAAoB,EAAE;AACjD;AAOA,SAAgB,IAAmC;CACjD,OAAO,EAAqB,GAAwB,SAAgC,EAAK;AAC3F"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAssetHandlerNavigate.js","names":[],"sources":["../../../src/assethandler/hooks/useAssetHandlerNavigate.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useNavigate, type NavigateOptions } from 'react-router';\nimport { useAssetHandler } from '../providers/AssetHandlerProvider';\nimport { joinPath } from '../utils/navigation';\n\n/**\n * Base-path-aware navigation for in-MFE links.\n *\n * The AssetHandler MFE is mounted under a host base path (e.g. `/assethandler`)\n * when integrated into an app shell, or at `/` when running standalone. React\n * Router's `navigate('/assets/...')` resolves against the HOST router root, so\n * an absolute in-MFE path would escape the mount and land on a nonexistent host\n * route (which the shell bounces to `/dashboard`).\n *\n * This hook prefixes the active `basePath` onto absolute string targets so\n * `navigate('/assets/asset-create')` correctly resolves to\n * `/assethandler/assets/asset-create` when integrated and `/assets/asset-create`\n * when standalone. Relative paths and numeric deltas (`navigate(-1)`) pass\n * through untouched.\n */\nexport function useAssetHandlerNavigate() {\n const navigate = useNavigate();\n const { basePath = '/' } = useAssetHandler();\n\n return useCallback(\n (to: string | number, options?: NavigateOptions) => {\n if (typeof to === 'number') {\n navigate(to);\n return;\n }\n const resolved = to.startsWith('/') ? joinPath(basePath, to) : to;\n navigate(resolved, options);\n },\n [navigate, basePath]\n );\n}\n"],"mappings":";;;;;AAoBA,SAAgB,IAA0B;CACxC,IAAM,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAiB;AAE5C,QAAO,GACJ,GAAqB,MAA8B;AAClD,MAAI,OAAO,KAAO,UAAU;AAC1B,KAAS,EAAG;AACZ;;AAGF,IADiB,EAAG,WAAW,IAAI,GAAG,EAAS,GAAU,EAAG,GAAG,GAC5C,EAAQ;IAE7B,CAAC,GAAU,EAAS,CACrB"}
1
+ {"version":3,"file":"useAssetHandlerNavigate.js","names":[],"sources":["../../../src/assethandler/hooks/useAssetHandlerNavigate.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useNavigate, type NavigateOptions } from 'react-router';\nimport { useAssetHandler } from '../providers/AssetHandlerProvider';\nimport { joinPath } from '../utils/navigation';\n\n/**\n * Base-path-aware navigation for in-MFE links.\n *\n * The AssetHandler MFE is mounted under a host base path (e.g. `/assethandler`)\n * when integrated into an app shell, or at `/` when running standalone. React\n * Router's `navigate('/assets/...')` resolves against the HOST router root, so\n * an absolute in-MFE path would escape the mount and land on a nonexistent host\n * route (which the shell bounces to `/dashboard`).\n *\n * This hook prefixes the active `basePath` onto absolute string targets so\n * `navigate('/assets/asset-create')` correctly resolves to\n * `/assethandler/assets/asset-create` when integrated and `/assets/asset-create`\n * when standalone. Relative paths and numeric deltas (`navigate(-1)`) pass\n * through untouched.\n */\nexport function useAssetHandlerNavigate() {\n const navigate = useNavigate();\n const { basePath = '/' } = useAssetHandler();\n\n return useCallback(\n (to: string | number, options?: NavigateOptions) => {\n if (typeof to === 'number') {\n navigate(to);\n return;\n }\n const resolved = to.startsWith('/') ? joinPath(basePath, to) : to;\n navigate(resolved, options);\n },\n [navigate, basePath]\n );\n}\n"],"mappings":";;;;;AAoBA,SAAgB,IAA0B;CACxC,IAAM,IAAW,EAAY,GACvB,EAAE,cAAW,QAAQ,EAAgB;CAE3C,OAAO,GACJ,GAAqB,MAA8B;EAClD,IAAI,OAAO,KAAO,UAAU;GAC1B,EAAS,CAAE;GACX;EACF;EAEA,EADiB,EAAG,WAAW,GAAG,IAAI,EAAS,GAAU,CAAE,IAAI,GAC5C,CAAO;CAC5B,GACA,CAAC,GAAU,CAAQ,CACrB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useCopy.js","names":[],"sources":["../../../src/assethandler/hooks/useCopy.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nimport { useAssetHandler, useAssetTerminology } from '../providers/AssetHandlerProvider';\n\ntype TranslationParams = Record<string, string | number>;\n\n/**\n * Resolves a single piece of module copy.\n *\n * @param key i18n key, e.g. \"assethandler.dashboard.metrics.totalAssets\".\n * @param fallback The module's own English copy, used when neither the host nor\n * the platform provides a string. May contain terminology\n * tokens (see {@link useCopy}).\n */\nexport type CopyFn = (key: string, fallback: string, params?: TranslationParams) => string;\n\n/** Terminology tokens substituted into resolved copy. */\nconst TOKEN_PATTERN = /\\{\\{(asset|assets|assetLower|assetsLower)\\}\\}/g;\n\n/**\n * Copy resolver for the module, in precedence order:\n *\n * 1. the host's `copy[key]` override (the `copy` prop on `AssetHandlerRoot`),\n * 2. the platform translation for `key`, when the locale provides one,\n * 3. the module's own default fallback.\n *\n * The resolved string then has its `{{asset}}` / `{{assets}}` /\n * `{{assetLower}}` / `{{assetsLower}}` tokens substituted with the terminology\n * from the `terminology` prop.\n *\n * With no `copy` and no `terminology` props the tokens resolve to\n * \"Asset\"/\"Assets\"/\"asset\"/\"assets\", so output is identical to the module's\n * previous `tWithFallback(t, key, fallback)` behaviour.\n */\nexport function useCopy(): CopyFn {\n const { t } = useI18n();\n const { copy } = useAssetHandler();\n const { asset, assets } = useAssetTerminology();\n\n return useCallback(\n (key: string, fallback: string, params?: TranslationParams): string => {\n // 1. host override, 2. platform translation, 3. module fallback.\n let resolved = copy?.[key];\n if (resolved === undefined) {\n const translated = t(key, params);\n resolved = translated === key ? fallback : translated;\n }\n\n if (!resolved.includes('{{')) return resolved;\n\n return resolved.replace(TOKEN_PATTERN, (_match, token: string) => {\n switch (token) {\n case 'asset':\n return asset;\n case 'assets':\n return assets;\n case 'assetLower':\n return asset.toLowerCase();\n case 'assetsLower':\n return assets.toLowerCase();\n default:\n return _match;\n }\n });\n },\n [copy, t, asset, assets]\n );\n}\n"],"mappings":";;;;AAkBA,IAAM,IAAgB;AAiBtB,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,GAAS,EACjB,EAAE,YAAS,GAAiB,EAC5B,EAAE,UAAO,cAAW,GAAqB;AAE/C,QAAO,GACJ,GAAa,GAAkB,MAAuC;EAErE,IAAI,IAAW,IAAO;AACtB,MAAI,MAAa,KAAA,GAAW;GAC1B,IAAM,IAAa,EAAE,GAAK,EAAO;AACjC,OAAW,MAAe,IAAM,IAAW;;AAK7C,SAFK,EAAS,SAAS,KAAK,GAErB,EAAS,QAAQ,IAAgB,GAAQ,MAAkB;AAChE,WAAQ,GAAR;IACE,KAAK,QACH,QAAO;IACT,KAAK,SACH,QAAO;IACT,KAAK,aACH,QAAO,EAAM,aAAa;IAC5B,KAAK,cACH,QAAO,EAAO,aAAa;IAC7B,QACE,QAAO;;IAEX,GAfmC;IAiBvC;EAAC;EAAM;EAAG;EAAO;EAAO,CACzB"}
1
+ {"version":3,"file":"useCopy.js","names":[],"sources":["../../../src/assethandler/hooks/useCopy.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nimport { useAssetHandler, useAssetTerminology } from '../providers/AssetHandlerProvider';\n\ntype TranslationParams = Record<string, string | number>;\n\n/**\n * Resolves a single piece of module copy.\n *\n * @param key i18n key, e.g. \"assethandler.dashboard.metrics.totalAssets\".\n * @param fallback The module's own English copy, used when neither the host nor\n * the platform provides a string. May contain terminology\n * tokens (see {@link useCopy}).\n */\nexport type CopyFn = (key: string, fallback: string, params?: TranslationParams) => string;\n\n/** Terminology tokens substituted into resolved copy. */\nconst TOKEN_PATTERN = /\\{\\{(asset|assets|assetLower|assetsLower)\\}\\}/g;\n\n/**\n * Copy resolver for the module, in precedence order:\n *\n * 1. the host's `copy[key]` override (the `copy` prop on `AssetHandlerRoot`),\n * 2. the platform translation for `key`, when the locale provides one,\n * 3. the module's own default fallback.\n *\n * The resolved string then has its `{{asset}}` / `{{assets}}` /\n * `{{assetLower}}` / `{{assetsLower}}` tokens substituted with the terminology\n * from the `terminology` prop.\n *\n * With no `copy` and no `terminology` props the tokens resolve to\n * \"Asset\"/\"Assets\"/\"asset\"/\"assets\", so output is identical to the module's\n * previous `tWithFallback(t, key, fallback)` behaviour.\n */\nexport function useCopy(): CopyFn {\n const { t } = useI18n();\n const { copy } = useAssetHandler();\n const { asset, assets } = useAssetTerminology();\n\n return useCallback(\n (key: string, fallback: string, params?: TranslationParams): string => {\n // 1. host override, 2. platform translation, 3. module fallback.\n let resolved = copy?.[key];\n if (resolved === undefined) {\n const translated = t(key, params);\n resolved = translated === key ? fallback : translated;\n }\n\n if (!resolved.includes('{{')) return resolved;\n\n return resolved.replace(TOKEN_PATTERN, (_match, token: string) => {\n switch (token) {\n case 'asset':\n return asset;\n case 'assets':\n return assets;\n case 'assetLower':\n return asset.toLowerCase();\n case 'assetsLower':\n return assets.toLowerCase();\n default:\n return _match;\n }\n });\n },\n [copy, t, asset, assets]\n );\n}\n"],"mappings":";;;;AAkBA,IAAM,IAAgB;AAiBtB,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,EAAQ,GAChB,EAAE,YAAS,EAAgB,GAC3B,EAAE,UAAO,cAAW,EAAoB;CAE9C,OAAO,GACJ,GAAa,GAAkB,MAAuC;EAErE,IAAI,IAAW,IAAO;EACtB,IAAI,MAAa,KAAA,GAAW;GAC1B,IAAM,IAAa,EAAE,GAAK,CAAM;GAChC,IAAW,MAAe,IAAM,IAAW;EAC7C;EAIA,OAFK,EAAS,SAAS,IAAI,IAEpB,EAAS,QAAQ,IAAgB,GAAQ,MAAkB;GAChE,QAAQ,GAAR;IACE,KAAK,SACH,OAAO;IACT,KAAK,UACH,OAAO;IACT,KAAK,cACH,OAAO,EAAM,YAAY;IAC3B,KAAK,eACH,OAAO,EAAO,YAAY;IAC5B,SACE,OAAO;GACX;EACF,CAAC,IAfoC;CAgBvC,GACA;EAAC;EAAM;EAAG;EAAO;CAAM,CACzB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useMaintenancePlans.js","names":[],"sources":["../../../src/assethandler/hooks/useMaintenancePlans.ts"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { notify } from '../utils/toast';\n\n/**\n * Recurring preventive-maintenance plans (BOFF-6031).\n *\n * These operations post-date the MFE's bootstrap query, so they are hand-written\n * `gql` documents rather than additions to it: the bootstrap is one large query\n * every page pays for, and plans are only needed on the plans surface.\n *\n * ── What the backend guarantees, and what this must therefore not do ─────────\n *\n * `nextDueAt` / `nextDueMeter` are DERIVED server-side on every read — they are\n * not stored. So this layer never caches a due date or recomputes one locally;\n * it re-reads after anything that could move it.\n *\n * `currentMeter`, `nextDueMeter`, `daysUntilDue` and `meterUntilDue` are all\n * genuinely nullable and null means \"not applicable\", never zero. An asset that\n * nobody meters has no meter reading; rendering that as 0 would claim a machine\n * sitting at zero hours.\n */\n\nexport const MAINTENANCE_PLAN_FIELDS = gql`\n fragment MaintenancePlanFields on MaintenancePlan {\n id\n assetId\n title\n description\n type\n priority\n isActive\n intervalDays\n intervalMeter\n lastServiceAt\n lastServiceMeter\n startAt\n startMeter\n leadTimeDays\n estimatedCost\n checklistTemplate\n createdAt\n updatedAt\n }\n`;\n\nconst MAINTENANCE_PLANS_QUERY = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n query AssetHandlerMaintenancePlans($assetId: ID, $includeInactive: Boolean) {\n maintenancePlans(assetId: $assetId, includeInactive: $includeInactive) {\n ...MaintenancePlanFields\n }\n }\n`;\n\nconst DUE_MAINTENANCE_PLANS_QUERY = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n query AssetHandlerDueMaintenancePlans($assetId: ID, $withinDays: Int) {\n dueMaintenancePlans(assetId: $assetId, withinDays: $withinDays) {\n plan {\n ...MaintenancePlanFields\n }\n nextDueAt\n nextDueMeter\n currentMeter\n meterUnit\n isDue\n isOverdue\n daysUntilDue\n meterUntilDue\n dueReason\n }\n }\n`;\n\nconst CREATE_MAINTENANCE_PLAN = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n mutation AssetHandlerCreateMaintenancePlan($input: CreateMaintenancePlanInput!) {\n createMaintenancePlan(input: $input) {\n ...MaintenancePlanFields\n }\n }\n`;\n\nconst UPDATE_MAINTENANCE_PLAN = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n mutation AssetHandlerUpdateMaintenancePlan($id: ID!, $input: UpdateMaintenancePlanInput!) {\n updateMaintenancePlan(id: $id, input: $input) {\n ...MaintenancePlanFields\n }\n }\n`;\n\nconst DELETE_MAINTENANCE_PLAN = gql`\n mutation AssetHandlerDeleteMaintenancePlan($id: ID!) {\n deleteMaintenancePlan(id: $id)\n }\n`;\n\nconst GENERATE_DUE_RECORDS = gql`\n mutation AssetHandlerGenerateDueMaintenanceRecords($input: GenerateMaintenanceRecordsInput) {\n generateDueMaintenanceRecords(input: $input) {\n dryRun\n generated\n skipped\n notes\n records {\n id\n title\n scheduledAt\n dueMeter\n }\n }\n }\n`;\n\nexport interface MaintenancePlan {\n id: string;\n assetId: string;\n title: string;\n description: string | null;\n type: string;\n priority: string;\n isActive: boolean;\n intervalDays: number | null;\n intervalMeter: number | null;\n lastServiceAt: string | null;\n lastServiceMeter: number | null;\n startAt: string | null;\n startMeter: number | null;\n leadTimeDays: number | null;\n estimatedCost: number | null;\n checklistTemplate: Record<string, unknown>[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface DueMaintenancePlan {\n plan: MaintenancePlan;\n nextDueAt: string | null;\n nextDueMeter: number | null;\n currentMeter: number | null;\n /** What that reading counts in. Null when the asset carries no unit. */\n meterUnit: string | null;\n isDue: boolean;\n isOverdue: boolean;\n daysUntilDue: number | null;\n meterUntilDue: number | null;\n dueReason: string | null;\n}\n\nexport interface GenerateResult {\n dryRun: boolean;\n generated: number;\n skipped: number;\n notes: string[];\n records: { id: string; title: string; scheduledAt: string | null; dueMeter: number | null }[];\n}\n\n/** The four values the backend accepts for a PLAN. */\nexport const PLAN_TYPES = ['PREVENTIVE', 'CORRECTIVE', 'PREDICTIVE', 'INSPECTION'] as const;\nexport const PLAN_PRIORITIES = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'] as const;\n\nconst REFETCH = ['AssetHandlerMaintenancePlans', 'AssetHandlerDueMaintenancePlans'];\n\nexport function useMaintenancePlans(\n options: { includeInactive?: boolean; withinDays?: number } = {}\n) {\n const { includeInactive = false, withinDays = 0 } = options;\n\n const plansQuery = useQuery<{ maintenancePlans: MaintenancePlan[] }>(MAINTENANCE_PLANS_QUERY, {\n variables: { includeInactive },\n fetchPolicy: 'cache-and-network',\n });\n\n const dueQuery = useQuery<{ dueMaintenancePlans: DueMaintenancePlan[] }>(\n DUE_MAINTENANCE_PLANS_QUERY,\n { variables: { withinDays }, fetchPolicy: 'cache-and-network' }\n );\n\n const [createPlan, createState] = useMutation(CREATE_MAINTENANCE_PLAN, {\n refetchQueries: REFETCH,\n onCompleted: () => notify.success('Plan created', 'It will raise work when it falls due.'),\n onError: (error) => notify.error('Could not create the plan', error.message),\n });\n\n const [updatePlan, updateState] = useMutation(UPDATE_MAINTENANCE_PLAN, {\n refetchQueries: REFETCH,\n onCompleted: () => notify.success('Plan updated'),\n onError: (error) => notify.error('Could not update the plan', error.message),\n });\n\n const [deletePlan, deleteState] = useMutation(DELETE_MAINTENANCE_PLAN, {\n refetchQueries: REFETCH,\n // Said plainly, because it is the reassuring half: deleting a schedule does\n // not delete the service history it produced.\n onCompleted: () =>\n notify.success('Plan deleted', 'The service records it raised have been kept.'),\n onError: (error) => notify.error('Could not delete the plan', error.message),\n });\n\n const [generateRecords, generateState] = useMutation<{\n generateDueMaintenanceRecords: GenerateResult;\n }>(GENERATE_DUE_RECORDS, {\n // Generated records are MaintenanceRecords, which the bootstrap owns — so\n // the scheduler and calendar pages must be refreshed too, or the new work\n // is invisible everywhere except here.\n refetchQueries: [...REFETCH, 'AssetHandlerBootstrap'],\n onError: (error) => notify.error('Could not raise the work', error.message),\n });\n\n return {\n plans: plansQuery.data?.maintenancePlans ?? [],\n duePlans: dueQuery.data?.dueMaintenancePlans ?? [],\n loading: plansQuery.loading || dueQuery.loading,\n error: plansQuery.error ?? dueQuery.error ?? null,\n refetch: () => {\n void plansQuery.refetch();\n void dueQuery.refetch();\n },\n createPlan,\n updatePlan,\n deletePlan,\n generateRecords,\n busy:\n createState.loading || updateState.loading || deleteState.loading || generateState.loading,\n };\n}\n"],"mappings":";;;;AAuBA,IAAa,IAA0B,CAAG;;;;;;;;;;;;;;;;;;;;;GAuBpC,IAA0B,CAAG;IAC/B,EAAwB;;;;;;GAQtB,IAA8B,CAAG;IACnC,EAAwB;;;;;;;;;;;;;;;;;GAmBtB,IAA0B,CAAG;IAC/B,EAAwB;;;;;;GAQtB,IAA0B,CAAG;IAC/B,EAAwB;;;;;;GAQtB,IAA0B,CAAG;;;;GAM7B,IAAuB,CAAG;;;;;;;;;;;;;;;GA6DnB,IAAa;CAAC;CAAc;CAAc;CAAc;CAAa,EACrE,IAAkB;CAAC;CAAY;CAAQ;CAAU;CAAM,EAE9D,IAAU,CAAC,gCAAgC,kCAAkC;AAEnF,SAAgB,EACd,IAA8D,EAAE,EAChE;CACA,IAAM,EAAE,qBAAkB,IAAO,gBAAa,MAAM,GAE9C,IAAa,EAAkD,GAAyB;EAC5F,WAAW,EAAE,oBAAiB;EAC9B,aAAa;EACd,CAAC,EAEI,IAAW,EACf,GACA;EAAE,WAAW,EAAE,eAAY;EAAE,aAAa;EAAqB,CAChE,EAEK,CAAC,GAAY,KAAe,EAAY,GAAyB;EACrE,gBAAgB;EAChB,mBAAmB,EAAO,QAAQ,gBAAgB,wCAAwC;EAC1F,UAAU,MAAU,EAAO,MAAM,6BAA6B,EAAM,QAAQ;EAC7E,CAAC,EAEI,CAAC,GAAY,KAAe,EAAY,GAAyB;EACrE,gBAAgB;EAChB,mBAAmB,EAAO,QAAQ,eAAe;EACjD,UAAU,MAAU,EAAO,MAAM,6BAA6B,EAAM,QAAQ;EAC7E,CAAC,EAEI,CAAC,GAAY,KAAe,EAAY,GAAyB;EACrE,gBAAgB;EAGhB,mBACE,EAAO,QAAQ,gBAAgB,gDAAgD;EACjF,UAAU,MAAU,EAAO,MAAM,6BAA6B,EAAM,QAAQ;EAC7E,CAAC,EAEI,CAAC,GAAiB,KAAiB,EAEtC,GAAsB;EAIvB,gBAAgB,CAAC,GAAG,GAAS,wBAAwB;EACrD,UAAU,MAAU,EAAO,MAAM,4BAA4B,EAAM,QAAQ;EAC5E,CAAC;AAEF,QAAO;EACL,OAAO,EAAW,MAAM,oBAAoB,EAAE;EAC9C,UAAU,EAAS,MAAM,uBAAuB,EAAE;EAClD,SAAS,EAAW,WAAW,EAAS;EACxC,OAAO,EAAW,SAAS,EAAS,SAAS;EAC7C,eAAe;AAER,GADA,EAAW,SAAS,EACpB,EAAS,SAAS;;EAEzB;EACA;EACA;EACA;EACA,MACE,EAAY,WAAW,EAAY,WAAW,EAAY,WAAW,EAAc;EACtF"}
1
+ {"version":3,"file":"useMaintenancePlans.js","names":[],"sources":["../../../src/assethandler/hooks/useMaintenancePlans.ts"],"sourcesContent":["import { gql } from '@apollo/client';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport { notify } from '../utils/toast';\n\n/**\n * Recurring preventive-maintenance plans (BOFF-6031).\n *\n * These operations post-date the MFE's bootstrap query, so they are hand-written\n * `gql` documents rather than additions to it: the bootstrap is one large query\n * every page pays for, and plans are only needed on the plans surface.\n *\n * ── What the backend guarantees, and what this must therefore not do ─────────\n *\n * `nextDueAt` / `nextDueMeter` are DERIVED server-side on every read — they are\n * not stored. So this layer never caches a due date or recomputes one locally;\n * it re-reads after anything that could move it.\n *\n * `currentMeter`, `nextDueMeter`, `daysUntilDue` and `meterUntilDue` are all\n * genuinely nullable and null means \"not applicable\", never zero. An asset that\n * nobody meters has no meter reading; rendering that as 0 would claim a machine\n * sitting at zero hours.\n */\n\nexport const MAINTENANCE_PLAN_FIELDS = gql`\n fragment MaintenancePlanFields on MaintenancePlan {\n id\n assetId\n title\n description\n type\n priority\n isActive\n intervalDays\n intervalMeter\n lastServiceAt\n lastServiceMeter\n startAt\n startMeter\n leadTimeDays\n estimatedCost\n checklistTemplate\n createdAt\n updatedAt\n }\n`;\n\nconst MAINTENANCE_PLANS_QUERY = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n query AssetHandlerMaintenancePlans($assetId: ID, $includeInactive: Boolean) {\n maintenancePlans(assetId: $assetId, includeInactive: $includeInactive) {\n ...MaintenancePlanFields\n }\n }\n`;\n\nconst DUE_MAINTENANCE_PLANS_QUERY = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n query AssetHandlerDueMaintenancePlans($assetId: ID, $withinDays: Int) {\n dueMaintenancePlans(assetId: $assetId, withinDays: $withinDays) {\n plan {\n ...MaintenancePlanFields\n }\n nextDueAt\n nextDueMeter\n currentMeter\n meterUnit\n isDue\n isOverdue\n daysUntilDue\n meterUntilDue\n dueReason\n }\n }\n`;\n\nconst CREATE_MAINTENANCE_PLAN = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n mutation AssetHandlerCreateMaintenancePlan($input: CreateMaintenancePlanInput!) {\n createMaintenancePlan(input: $input) {\n ...MaintenancePlanFields\n }\n }\n`;\n\nconst UPDATE_MAINTENANCE_PLAN = gql`\n ${MAINTENANCE_PLAN_FIELDS}\n mutation AssetHandlerUpdateMaintenancePlan($id: ID!, $input: UpdateMaintenancePlanInput!) {\n updateMaintenancePlan(id: $id, input: $input) {\n ...MaintenancePlanFields\n }\n }\n`;\n\nconst DELETE_MAINTENANCE_PLAN = gql`\n mutation AssetHandlerDeleteMaintenancePlan($id: ID!) {\n deleteMaintenancePlan(id: $id)\n }\n`;\n\nconst GENERATE_DUE_RECORDS = gql`\n mutation AssetHandlerGenerateDueMaintenanceRecords($input: GenerateMaintenanceRecordsInput) {\n generateDueMaintenanceRecords(input: $input) {\n dryRun\n generated\n skipped\n notes\n records {\n id\n title\n scheduledAt\n dueMeter\n }\n }\n }\n`;\n\nexport interface MaintenancePlan {\n id: string;\n assetId: string;\n title: string;\n description: string | null;\n type: string;\n priority: string;\n isActive: boolean;\n intervalDays: number | null;\n intervalMeter: number | null;\n lastServiceAt: string | null;\n lastServiceMeter: number | null;\n startAt: string | null;\n startMeter: number | null;\n leadTimeDays: number | null;\n estimatedCost: number | null;\n checklistTemplate: Record<string, unknown>[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface DueMaintenancePlan {\n plan: MaintenancePlan;\n nextDueAt: string | null;\n nextDueMeter: number | null;\n currentMeter: number | null;\n /** What that reading counts in. Null when the asset carries no unit. */\n meterUnit: string | null;\n isDue: boolean;\n isOverdue: boolean;\n daysUntilDue: number | null;\n meterUntilDue: number | null;\n dueReason: string | null;\n}\n\nexport interface GenerateResult {\n dryRun: boolean;\n generated: number;\n skipped: number;\n notes: string[];\n records: { id: string; title: string; scheduledAt: string | null; dueMeter: number | null }[];\n}\n\n/** The four values the backend accepts for a PLAN. */\nexport const PLAN_TYPES = ['PREVENTIVE', 'CORRECTIVE', 'PREDICTIVE', 'INSPECTION'] as const;\nexport const PLAN_PRIORITIES = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'] as const;\n\nconst REFETCH = ['AssetHandlerMaintenancePlans', 'AssetHandlerDueMaintenancePlans'];\n\nexport function useMaintenancePlans(\n options: { includeInactive?: boolean; withinDays?: number } = {}\n) {\n const { includeInactive = false, withinDays = 0 } = options;\n\n const plansQuery = useQuery<{ maintenancePlans: MaintenancePlan[] }>(MAINTENANCE_PLANS_QUERY, {\n variables: { includeInactive },\n fetchPolicy: 'cache-and-network',\n });\n\n const dueQuery = useQuery<{ dueMaintenancePlans: DueMaintenancePlan[] }>(\n DUE_MAINTENANCE_PLANS_QUERY,\n { variables: { withinDays }, fetchPolicy: 'cache-and-network' }\n );\n\n const [createPlan, createState] = useMutation(CREATE_MAINTENANCE_PLAN, {\n refetchQueries: REFETCH,\n onCompleted: () => notify.success('Plan created', 'It will raise work when it falls due.'),\n onError: (error) => notify.error('Could not create the plan', error.message),\n });\n\n const [updatePlan, updateState] = useMutation(UPDATE_MAINTENANCE_PLAN, {\n refetchQueries: REFETCH,\n onCompleted: () => notify.success('Plan updated'),\n onError: (error) => notify.error('Could not update the plan', error.message),\n });\n\n const [deletePlan, deleteState] = useMutation(DELETE_MAINTENANCE_PLAN, {\n refetchQueries: REFETCH,\n // Said plainly, because it is the reassuring half: deleting a schedule does\n // not delete the service history it produced.\n onCompleted: () =>\n notify.success('Plan deleted', 'The service records it raised have been kept.'),\n onError: (error) => notify.error('Could not delete the plan', error.message),\n });\n\n const [generateRecords, generateState] = useMutation<{\n generateDueMaintenanceRecords: GenerateResult;\n }>(GENERATE_DUE_RECORDS, {\n // Generated records are MaintenanceRecords, which the bootstrap owns — so\n // the scheduler and calendar pages must be refreshed too, or the new work\n // is invisible everywhere except here.\n refetchQueries: [...REFETCH, 'AssetHandlerBootstrap'],\n onError: (error) => notify.error('Could not raise the work', error.message),\n });\n\n return {\n plans: plansQuery.data?.maintenancePlans ?? [],\n duePlans: dueQuery.data?.dueMaintenancePlans ?? [],\n loading: plansQuery.loading || dueQuery.loading,\n error: plansQuery.error ?? dueQuery.error ?? null,\n refetch: () => {\n void plansQuery.refetch();\n void dueQuery.refetch();\n },\n createPlan,\n updatePlan,\n deletePlan,\n generateRecords,\n busy:\n createState.loading || updateState.loading || deleteState.loading || generateState.loading,\n };\n}\n"],"mappings":";;;;AAuBA,IAAa,IAA0B,CAAG;;;;;;;;;;;;;;;;;;;;;GAuBpC,IAA0B,CAAG;IAC/B,EAAwB;;;;;;GAQtB,IAA8B,CAAG;IACnC,EAAwB;;;;;;;;;;;;;;;;;GAmBtB,IAA0B,CAAG;IAC/B,EAAwB;;;;;;GAQtB,IAA0B,CAAG;IAC/B,EAAwB;;;;;;GAQtB,IAA0B,CAAG;;;;GAM7B,IAAuB,CAAG;;;;;;;;;;;;;;;GA6DnB,IAAa;CAAC;CAAc;CAAc;CAAc;AAAY,GACpE,IAAkB;CAAC;CAAY;CAAQ;CAAU;AAAK,GAE7D,IAAU,CAAC,gCAAgC,iCAAiC;AAElF,SAAgB,EACd,IAA8D,CAAC,GAC/D;CACA,IAAM,EAAE,qBAAkB,IAAO,gBAAa,MAAM,GAE9C,IAAa,EAAkD,GAAyB;EAC5F,WAAW,EAAE,mBAAgB;EAC7B,aAAa;CACf,CAAC,GAEK,IAAW,EACf,GACA;EAAE,WAAW,EAAE,cAAW;EAAG,aAAa;CAAoB,CAChE,GAEM,CAAC,GAAY,KAAe,EAAY,GAAyB;EACrE,gBAAgB;EAChB,mBAAmB,EAAO,QAAQ,gBAAgB,uCAAuC;EACzF,UAAU,MAAU,EAAO,MAAM,6BAA6B,EAAM,OAAO;CAC7E,CAAC,GAEK,CAAC,GAAY,KAAe,EAAY,GAAyB;EACrE,gBAAgB;EAChB,mBAAmB,EAAO,QAAQ,cAAc;EAChD,UAAU,MAAU,EAAO,MAAM,6BAA6B,EAAM,OAAO;CAC7E,CAAC,GAEK,CAAC,GAAY,KAAe,EAAY,GAAyB;EACrE,gBAAgB;EAGhB,mBACE,EAAO,QAAQ,gBAAgB,+CAA+C;EAChF,UAAU,MAAU,EAAO,MAAM,6BAA6B,EAAM,OAAO;CAC7E,CAAC,GAEK,CAAC,GAAiB,KAAiB,EAEtC,GAAsB;EAIvB,gBAAgB,CAAC,GAAG,GAAS,uBAAuB;EACpD,UAAU,MAAU,EAAO,MAAM,4BAA4B,EAAM,OAAO;CAC5E,CAAC;CAED,OAAO;EACL,OAAO,EAAW,MAAM,oBAAoB,CAAC;EAC7C,UAAU,EAAS,MAAM,uBAAuB,CAAC;EACjD,SAAS,EAAW,WAAW,EAAS;EACxC,OAAO,EAAW,SAAS,EAAS,SAAS;EAC7C,eAAe;GAEb,AADA,EAAgB,QAAQ,GACxB,EAAc,QAAQ;EACxB;EACA;EACA;EACA;EACA;EACA,MACE,EAAY,WAAW,EAAY,WAAW,EAAY,WAAW,EAAc;CACvF;AACF"}