@stackcraftmx/calcita 0.27.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/README.md +149 -0
  2. package/dist/DataTable/AuditTrailDialog.js +18 -14
  3. package/dist/DataTable/AuditTrailDialog.js.map +1 -1
  4. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +12 -6
  5. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -1
  6. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +8 -3
  7. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -1
  8. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +26 -18
  9. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -1
  10. package/dist/DataTable/EmptyState.js +8 -3
  11. package/dist/DataTable/EmptyState.js.map +1 -1
  12. package/dist/DataTable/FilterChips.js +11 -5
  13. package/dist/DataTable/FilterChips.js.map +1 -1
  14. package/dist/DataTable/GoToPage.js +9 -4
  15. package/dist/DataTable/GoToPage.js.map +1 -1
  16. package/dist/DataTable/ServerTable.js +74 -61
  17. package/dist/DataTable/ServerTable.js.map +1 -1
  18. package/dist/DataTable/columns.js +1 -8
  19. package/dist/DataTable/columns.js.map +1 -1
  20. package/dist/access/PermissionMatrix.js +18 -9
  21. package/dist/access/PermissionMatrix.js.map +1 -1
  22. package/dist/account/AccountSecuritySection.js +8 -3
  23. package/dist/account/AccountSecuritySection.js.map +1 -1
  24. package/dist/account/DemoTotpCodeButton.js +8 -3
  25. package/dist/account/DemoTotpCodeButton.js.map +1 -1
  26. package/dist/account/ProfileScreen.js +19 -13
  27. package/dist/account/ProfileScreen.js.map +1 -1
  28. package/dist/account/SignInScreen.js +6 -2
  29. package/dist/account/SignInScreen.js.map +1 -1
  30. package/dist/appShell/AccountMenu.js +13 -5
  31. package/dist/appShell/AccountMenu.js.map +1 -1
  32. package/dist/appShell/AppLayout.js +100 -71
  33. package/dist/appShell/AppLayout.js.map +1 -1
  34. package/dist/appShell/AppearanceSettings.js +21 -13
  35. package/dist/appShell/AppearanceSettings.js.map +1 -1
  36. package/dist/appShell/AuthLayout.js +26 -13
  37. package/dist/appShell/AuthLayout.js.map +1 -1
  38. package/dist/appShell/BarActions.js +10 -5
  39. package/dist/appShell/BarActions.js.map +1 -1
  40. package/dist/appShell/BarCapsule.js +9 -4
  41. package/dist/appShell/BarCapsule.js.map +1 -1
  42. package/dist/appShell/BarSearch.js +7 -3
  43. package/dist/appShell/BarSearch.js.map +1 -1
  44. package/dist/appShell/HeaderTools.js +20 -15
  45. package/dist/appShell/HeaderTools.js.map +1 -1
  46. package/dist/appShell/MobileTabBar.js +25 -14
  47. package/dist/appShell/MobileTabBar.js.map +1 -1
  48. package/dist/appShell/SettingsMenu.js +7 -3
  49. package/dist/appShell/SettingsMenu.js.map +1 -1
  50. package/dist/appShell/SideMenu.js +53 -35
  51. package/dist/appShell/SideMenu.js.map +1 -1
  52. package/dist/appShell/SideMenuEntry.js +18 -9
  53. package/dist/appShell/SideMenuEntry.js.map +1 -1
  54. package/dist/appShell/SubmenuActionsMenu.js +6 -2
  55. package/dist/appShell/SubmenuActionsMenu.js.map +1 -1
  56. package/dist/appShell/TabBarEditor.js +16 -7
  57. package/dist/appShell/TabBarEditor.js.map +1 -1
  58. package/dist/appShell/TopMenu.js +12 -7
  59. package/dist/appShell/TopMenu.js.map +1 -1
  60. package/dist/appShell/Wordmark.js +6 -2
  61. package/dist/appShell/Wordmark.js.map +1 -1
  62. package/dist/auth/PasswordChecklist.js +14 -7
  63. package/dist/auth/PasswordChecklist.js.map +1 -1
  64. package/dist/calendar/EventCalendar.js +26 -19
  65. package/dist/calendar/EventCalendar.js.map +1 -1
  66. package/dist/calendar/EventDetails.js +28 -13
  67. package/dist/calendar/EventDetails.js.map +1 -1
  68. package/dist/downloads/DownloadManager.js +34 -18
  69. package/dist/downloads/DownloadManager.js.map +1 -1
  70. package/dist/feedback/ConfirmDialog.js +22 -17
  71. package/dist/feedback/ConfirmDialog.js.map +1 -1
  72. package/dist/feedback/ModalWaiting.js +12 -5
  73. package/dist/feedback/ModalWaiting.js.map +1 -1
  74. package/dist/feedback/NewBuildNotice.js +16 -8
  75. package/dist/feedback/NewBuildNotice.js.map +1 -1
  76. package/dist/filepond/FileDropzone.js +39 -31
  77. package/dist/filepond/FileDropzone.js.map +1 -1
  78. package/dist/forms/FormProblemAlert.js +4 -1
  79. package/dist/forms/FormProblemAlert.js.map +1 -1
  80. package/dist/forms/auth/SignInForm.js +6 -2
  81. package/dist/forms/auth/SignInForm.js.map +1 -1
  82. package/dist/forms/security/SecondStepForm.js +6 -2
  83. package/dist/forms/security/SecondStepForm.js.map +1 -1
  84. package/dist/forms/security/TwoStepVerificationCard.js +19 -9
  85. package/dist/forms/security/TwoStepVerificationCard.js.map +1 -1
  86. package/dist/hookForm/FormProblemAlert.js +4 -1
  87. package/dist/hookForm/FormProblemAlert.js.map +1 -1
  88. package/dist/inbox/InboxLayout.js +47 -29
  89. package/dist/inbox/InboxLayout.js.map +1 -1
  90. package/dist/inbox/MessageList.js +53 -32
  91. package/dist/inbox/MessageList.js.map +1 -1
  92. package/dist/inbox/MessageView.js +31 -15
  93. package/dist/inbox/MessageView.js.map +1 -1
  94. package/dist/index.js +7 -1
  95. package/dist/index.js.map +1 -1
  96. package/dist/inputs/ColorInput.js +22 -17
  97. package/dist/inputs/ColorInput.js.map +1 -1
  98. package/dist/inputs/FormSection.js +66 -63
  99. package/dist/inputs/FormSection.js.map +1 -1
  100. package/dist/inputs/SelectInput.js +21 -16
  101. package/dist/inputs/SelectInput.js.map +1 -1
  102. package/dist/inputs/TextInput.js +25 -20
  103. package/dist/inputs/TextInput.js.map +1 -1
  104. package/dist/inputs/WizardLayout.js +21 -15
  105. package/dist/inputs/WizardLayout.js.map +1 -1
  106. package/dist/kanban/KanbanBoard.js +82 -50
  107. package/dist/kanban/KanbanBoard.js.map +1 -1
  108. package/dist/maps/MapView.js +19 -14
  109. package/dist/maps/MapView.js.map +1 -1
  110. package/dist/pwa/InstallAppSetting.js +4 -1
  111. package/dist/pwa/InstallAppSetting.js.map +1 -1
  112. package/dist/pwa/InstallInstructionsDialog.js +6 -2
  113. package/dist/pwa/InstallInstructionsDialog.js.map +1 -1
  114. package/dist/pwa/InstallPromptBanner.js +10 -5
  115. package/dist/pwa/InstallPromptBanner.js.map +1 -1
  116. package/dist/security/ActivityLog.js +6 -2
  117. package/dist/security/ActivityLog.js.map +1 -1
  118. package/dist/security/RecoveryCodesDialog.js +8 -3
  119. package/dist/security/RecoveryCodesDialog.js.map +1 -1
  120. package/dist/security/SessionsCard.js +12 -5
  121. package/dist/security/SessionsCard.js.map +1 -1
  122. package/dist/theme/components/glassComponents.js +19 -16
  123. package/dist/theme/components/glassComponents.js.map +1 -1
  124. package/dist/theme/components/minimalComponents.js +10 -6
  125. package/dist/theme/components/minimalComponents.js.map +1 -1
  126. package/dist/theme/createToolkitTheme.js +23 -6
  127. package/dist/theme/createToolkitTheme.js.map +1 -1
  128. package/dist/theme/cssTokens.js +23 -0
  129. package/dist/theme/cssTokens.js.map +1 -0
  130. package/dist/theme/glassSurface.js +64 -10
  131. package/dist/theme/glassSurface.js.map +1 -1
  132. package/dist/theme/glassToasterStyles.js +2 -3
  133. package/dist/theme/glassToasterStyles.js.map +1 -1
  134. package/dist/theme/themePieces.js +16 -0
  135. package/dist/theme/themePieces.js.map +1 -0
  136. package/dist/types/DataTable/AuditTrailDialog.d.ts +1 -1
  137. package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +1 -1
  138. package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +1 -1
  139. package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +1 -1
  140. package/dist/types/DataTable/EmptyState.d.ts +1 -1
  141. package/dist/types/DataTable/FilterChips.d.ts +1 -1
  142. package/dist/types/DataTable/GoToPage.d.ts +1 -1
  143. package/dist/types/DataTable/ServerTable.d.ts +1 -1
  144. package/dist/types/access/PermissionMatrix.d.ts +1 -1
  145. package/dist/types/account/AccountSecuritySection.d.ts +1 -1
  146. package/dist/types/account/DemoTotpCodeButton.d.ts +1 -1
  147. package/dist/types/account/ProfileScreen.d.ts +1 -1
  148. package/dist/types/account/SignInScreen.d.ts +1 -1
  149. package/dist/types/appShell/AccountMenu.d.ts +1 -1
  150. package/dist/types/appShell/AppLayout.d.ts +1 -1
  151. package/dist/types/appShell/AppearanceSettings.d.ts +1 -1
  152. package/dist/types/appShell/AuthLayout.d.ts +1 -1
  153. package/dist/types/appShell/BarActions.d.ts +1 -1
  154. package/dist/types/appShell/BarCapsule.d.ts +1 -1
  155. package/dist/types/appShell/BarSearch.d.ts +1 -1
  156. package/dist/types/appShell/HeaderTools.d.ts +1 -1
  157. package/dist/types/appShell/MobileTabBar.d.ts +1 -1
  158. package/dist/types/appShell/SettingsMenu.d.ts +1 -1
  159. package/dist/types/appShell/SideMenu.d.ts +1 -1
  160. package/dist/types/appShell/SideMenuEntry.d.ts +1 -1
  161. package/dist/types/appShell/SubmenuActionsMenu.d.ts +1 -1
  162. package/dist/types/appShell/TabBarEditor.d.ts +1 -1
  163. package/dist/types/appShell/TopMenu.d.ts +1 -1
  164. package/dist/types/appShell/Wordmark.d.ts +1 -1
  165. package/dist/types/auth/PasswordChecklist.d.ts +1 -1
  166. package/dist/types/calendar/EventCalendar.d.ts +1 -1
  167. package/dist/types/calendar/EventDetails.d.ts +1 -1
  168. package/dist/types/feedback/ConfirmDialog.d.ts +1 -1
  169. package/dist/types/feedback/ModalWaiting.d.ts +1 -1
  170. package/dist/types/feedback/NewBuildNotice.d.ts +1 -1
  171. package/dist/types/filepond/FileDropzone.d.ts +1 -1
  172. package/dist/types/forms/auth/SignInForm.d.ts +1 -1
  173. package/dist/types/forms/security/SecondStepForm.d.ts +1 -1
  174. package/dist/types/forms/security/TwoStepVerificationCard.d.ts +1 -1
  175. package/dist/types/inbox/InboxLayout.d.ts +1 -1
  176. package/dist/types/inbox/MessageList.d.ts +1 -1
  177. package/dist/types/inbox/MessageView.d.ts +1 -1
  178. package/dist/types/index.d.ts +2 -1
  179. package/dist/types/inputs/ColorInput.d.ts +1 -1
  180. package/dist/types/inputs/FormSection.d.ts +2 -2
  181. package/dist/types/inputs/SelectInput.d.ts +1 -1
  182. package/dist/types/inputs/TextInput.d.ts +1 -1
  183. package/dist/types/inputs/WizardLayout.d.ts +1 -1
  184. package/dist/types/kanban/KanbanBoard.d.ts +1 -1
  185. package/dist/types/maps/MapView.d.ts +1 -1
  186. package/dist/types/pwa/InstallInstructionsDialog.d.ts +1 -1
  187. package/dist/types/pwa/InstallPromptBanner.d.ts +1 -1
  188. package/dist/types/security/ActivityLog.d.ts +1 -1
  189. package/dist/types/security/RecoveryCodesDialog.d.ts +1 -1
  190. package/dist/types/security/SessionsCard.d.ts +1 -1
  191. package/dist/types/theme/createToolkitTheme.d.ts +33 -1
  192. package/dist/types/theme/cssTokens.d.ts +46 -0
  193. package/dist/types/theme/glassSurface.d.ts +57 -1
  194. package/dist/types/theme/themePieces.d.ts +20 -0
  195. package/dist/types/ui/actions/ActionsMenu.d.ts +1 -1
  196. package/dist/types/ui/actions/DownloadMenu.d.ts +1 -1
  197. package/dist/types/ui/actions/SelectionActions.d.ts +1 -1
  198. package/dist/types/ui/filters/DateRangeFilter.d.ts +1 -1
  199. package/dist/types/ui/filters/PeriodRangeSelector.d.ts +1 -1
  200. package/dist/types/ui/filters/QuickFilters.d.ts +1 -1
  201. package/dist/types/ui/filters/SegmentedControl.d.ts +7 -2
  202. package/dist/types/ui/labels/StatusChip.d.ts +1 -1
  203. package/dist/types/ui/labels/Tag.d.ts +1 -1
  204. package/dist/types/ui/layout/CollapsibleSection.d.ts +1 -1
  205. package/dist/types/ui/layout/ContentDialog.d.ts +1 -1
  206. package/dist/types/ui/layout/DefinitionList.d.ts +1 -1
  207. package/dist/types/ui/layout/DetailHeader.d.ts +1 -1
  208. package/dist/types/ui/layout/ErrorPage.d.ts +1 -1
  209. package/dist/types/ui/layout/GlassPanel.d.ts +1 -1
  210. package/dist/types/ui/layout/PageHeader.d.ts +1 -1
  211. package/dist/types/ui/layout/PageHeading.d.ts +1 -1
  212. package/dist/types/ui/layout/ProfileHeader.d.ts +1 -1
  213. package/dist/types/ui/layout/ScrollableRow.d.ts +1 -1
  214. package/dist/types/ui/layout/SectionCard.d.ts +1 -1
  215. package/dist/types/ui/metrics/BarList.d.ts +1 -1
  216. package/dist/types/ui/metrics/CalendarHeatmap.d.ts +1 -1
  217. package/dist/types/ui/metrics/ChartTooltip.d.ts +1 -1
  218. package/dist/types/ui/metrics/ColumnChart.d.ts +1 -1
  219. package/dist/types/ui/metrics/LineChart.d.ts +1 -1
  220. package/dist/types/ui/metrics/MetricCard.d.ts +1 -1
  221. package/dist/types/ui/metrics/TableToggle.d.ts +1 -1
  222. package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +1 -1
  223. package/dist/types/ui/navigation/FontSizeToggle.d.ts +1 -1
  224. package/dist/types/ui/navigation/LanguageToggle.d.ts +1 -1
  225. package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +1 -1
  226. package/dist/types/ui/timeline/GroupedTimeline.d.ts +1 -1
  227. package/dist/types/upload/FileDropzone.d.ts +1 -1
  228. package/dist/ui/actions/ActionsMenu.js +9 -4
  229. package/dist/ui/actions/ActionsMenu.js.map +1 -1
  230. package/dist/ui/actions/DownloadMenu.js +21 -17
  231. package/dist/ui/actions/DownloadMenu.js.map +1 -1
  232. package/dist/ui/actions/SelectionActions.js +15 -7
  233. package/dist/ui/actions/SelectionActions.js.map +1 -1
  234. package/dist/ui/filters/DateRangeFilter.js +11 -5
  235. package/dist/ui/filters/DateRangeFilter.js.map +1 -1
  236. package/dist/ui/filters/PeriodRangeSelector.js +11 -5
  237. package/dist/ui/filters/PeriodRangeSelector.js.map +1 -1
  238. package/dist/ui/filters/QuickFilters.js +16 -8
  239. package/dist/ui/filters/QuickFilters.js.map +1 -1
  240. package/dist/ui/filters/SegmentedControl.js +12 -5
  241. package/dist/ui/filters/SegmentedControl.js.map +1 -1
  242. package/dist/ui/labels/StatusChip.js +35 -25
  243. package/dist/ui/labels/StatusChip.js.map +1 -1
  244. package/dist/ui/labels/Tag.js +8 -3
  245. package/dist/ui/labels/Tag.js.map +1 -1
  246. package/dist/ui/layout/CollapsibleSection.js +18 -8
  247. package/dist/ui/layout/CollapsibleSection.js.map +1 -1
  248. package/dist/ui/layout/ContentDialog.js +13 -6
  249. package/dist/ui/layout/ContentDialog.js.map +1 -1
  250. package/dist/ui/layout/DefinitionList.js +13 -6
  251. package/dist/ui/layout/DefinitionList.js.map +1 -1
  252. package/dist/ui/layout/DetailHeader.js +14 -6
  253. package/dist/ui/layout/DetailHeader.js.map +1 -1
  254. package/dist/ui/layout/ErrorPage.js +20 -15
  255. package/dist/ui/layout/ErrorPage.js.map +1 -1
  256. package/dist/ui/layout/FullPageLoader.js +4 -1
  257. package/dist/ui/layout/FullPageLoader.js.map +1 -1
  258. package/dist/ui/layout/GlassPanel.js +8 -4
  259. package/dist/ui/layout/GlassPanel.js.map +1 -1
  260. package/dist/ui/layout/PageHeader.js +10 -4
  261. package/dist/ui/layout/PageHeader.js.map +1 -1
  262. package/dist/ui/layout/PageHeading.js +17 -8
  263. package/dist/ui/layout/PageHeading.js.map +1 -1
  264. package/dist/ui/layout/ProfileHeader.js +21 -10
  265. package/dist/ui/layout/ProfileHeader.js.map +1 -1
  266. package/dist/ui/layout/ScrollableRow.js +19 -15
  267. package/dist/ui/layout/ScrollableRow.js.map +1 -1
  268. package/dist/ui/layout/SectionCard.js +10 -4
  269. package/dist/ui/layout/SectionCard.js.map +1 -1
  270. package/dist/ui/metrics/BarList.js +9 -4
  271. package/dist/ui/metrics/BarList.js.map +1 -1
  272. package/dist/ui/metrics/CalendarHeatmap.js +40 -21
  273. package/dist/ui/metrics/CalendarHeatmap.js.map +1 -1
  274. package/dist/ui/metrics/ChartTooltip.js +6 -2
  275. package/dist/ui/metrics/ChartTooltip.js.map +1 -1
  276. package/dist/ui/metrics/ColumnChart.js +22 -18
  277. package/dist/ui/metrics/ColumnChart.js.map +1 -1
  278. package/dist/ui/metrics/LineChart.js +20 -16
  279. package/dist/ui/metrics/LineChart.js.map +1 -1
  280. package/dist/ui/metrics/MetricCard.js +42 -24
  281. package/dist/ui/metrics/MetricCard.js.map +1 -1
  282. package/dist/ui/metrics/TableToggle.js +7 -2
  283. package/dist/ui/metrics/TableToggle.js.map +1 -1
  284. package/dist/ui/metrics/chartParts.js +14 -5
  285. package/dist/ui/metrics/chartParts.js.map +1 -1
  286. package/dist/ui/navigation/ColorSchemeToggle.js +8 -4
  287. package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -1
  288. package/dist/ui/navigation/FontSizeToggle.js +6 -2
  289. package/dist/ui/navigation/FontSizeToggle.js.map +1 -1
  290. package/dist/ui/navigation/LanguageToggle.js +8 -4
  291. package/dist/ui/navigation/LanguageToggle.js.map +1 -1
  292. package/dist/ui/navigation/PageBreadcrumbs.js +12 -6
  293. package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -1
  294. package/dist/ui/timeline/GroupedTimeline.js +26 -13
  295. package/dist/ui/timeline/GroupedTimeline.js.map +1 -1
  296. package/dist/upload/FileDropzone.js +35 -25
  297. package/dist/upload/FileDropzone.js.map +1 -1
  298. package/package.json +1 -1
@@ -13,6 +13,10 @@ import ChartTooltip from "./ChartTooltip.js";
13
13
  import TableToggle, { CHART_VIEW } from "./TableToggle.js";
14
14
  import { BAR_MIN_POINT_SIZE, barLabelValueOf } from "./barListLabels.js";
15
15
  import { useChartColors } from "./chartParts.js";
16
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
17
+ const THEME_NAME = "CalcitaBarList";
18
+ const BarListRow = piecePart(THEME_NAME, "Row", TableRow);
19
+ const BarListChart = piecePart(THEME_NAME, "Chart", Box);
16
20
  const ROW_HEIGHT_PIXELS = 36;
17
21
  function ValueLabel({ x, y, width, height, value, colors, formatNumber }) {
18
22
  return /* @__PURE__ */ jsxs("text", { x: x + width + 8, y: y + height / 2, dominantBaseline: "central", fontSize: 13, children: [
@@ -20,7 +24,8 @@ function ValueLabel({ x, y, width, height, value, colors, formatNumber }) {
20
24
  value.detail && /* @__PURE__ */ jsx("tspan", { fill: colors.muted, fontSize: 12, children: ` ${value.detail}` })
21
25
  ] });
22
26
  }
23
- function BarList({ items, onSelect, emptyLabel, tone = "primary", texts, defaultView = CHART_VIEW.chart, onViewChange }) {
27
+ function BarList(props) {
28
+ const { items, onSelect, emptyLabel, tone = "primary", texts, defaultView = CHART_VIEW.chart, onViewChange } = usePieceProps(props, THEME_NAME);
24
29
  const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);
25
30
  const toggleView = () => {
26
31
  setAsTable(!asTable);
@@ -36,11 +41,11 @@ function BarList({ items, onSelect, emptyLabel, tone = "primary", texts, default
36
41
  return /* @__PURE__ */ jsxs(Box, { children: [
37
42
  /* @__PURE__ */ jsx(TableToggle, { asTable, onToggle: toggleView, texts }),
38
43
  asTable ? /* @__PURE__ */ jsx(Table, { size: "small", children: /* @__PURE__ */ jsx(TableBody, { children: items.map((item) => /* @__PURE__ */ jsxs(
39
- TableRow,
44
+ BarListRow,
40
45
  {
41
46
  hover: Boolean(onSelect),
42
47
  onClick: onSelect ? () => onSelect(item) : void 0,
43
- sx: { cursor: onSelect ? "pointer" : "default" },
48
+ ownSx: { cursor: onSelect ? "pointer" : "default" },
44
49
  children: [
45
50
  /* @__PURE__ */ jsx(TableCell, { children: item.label }),
46
51
  /* @__PURE__ */ jsxs(TableCell, { align: "right", children: [
@@ -51,7 +56,7 @@ function BarList({ items, onSelect, emptyLabel, tone = "primary", texts, default
51
56
  ]
52
57
  },
53
58
  item.key
54
- )) }) }) : /* @__PURE__ */ jsx(Box, { sx: { height: items.length * ROW_HEIGHT_PIXELS, color: `${tone}.main` }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart, { data: items, layout: "vertical", margin: { top: 0, bottom: 0, left: 0, right: 16 + longestValue * 7 }, children: [
59
+ )) }) }) : /* @__PURE__ */ jsx(BarListChart, { ownSx: { height: items.length * ROW_HEIGHT_PIXELS, color: `${tone}.main` }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart, { data: items, layout: "vertical", margin: { top: 0, bottom: 0, left: 0, right: 16 + longestValue * 7 }, children: [
55
60
  /* @__PURE__ */ jsx(XAxis, { type: "number", hide: true, domain: [0, (dataMax) => Math.max(dataMax, 1)] }),
56
61
  /* @__PURE__ */ jsx(
57
62
  YAxis,
@@ -1 +1 @@
1
- {"version":3,"file":"BarList.js","sources":["../../../src/ui/metrics/BarList.jsx"],"sourcesContent":["// Barras horizontales de UNA serie con su nombre a la izquierda y su valor en la punta (ventas por producto,\n// cuentas por organización), dibujadas con Recharts.\n//\n// Horizontales porque los nombres son largos (\"Empresa / Área de ventas\"): se leen completos sin rotarlos. Una serie → un\n// color (el del tono, vía currentColor: los atributos SVG no leen var(...) pero sí currentColor); el valor va en tinta,\n// nunca del color de la barra; y cada barra puede llevar a la pantalla que la explica.\n//\n// OJO: el número y el detalle de la punta salen del renglón de la barra (barListLabels.js), nunca de items[index]: Recharts\n// descarta las barras de ancho 0 y renumera las etiquetas, y el detalle se corría al renglón de arriba.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Table from '@mui/material/Table';\nimport TableBody from '@mui/material/TableBody';\nimport TableCell from '@mui/material/TableCell';\nimport TableRow from '@mui/material/TableRow';\nimport Typography from '@mui/material/Typography';\nimport {Bar, BarChart, LabelList, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport ChartTooltip from '@/ui/metrics/ChartTooltip.jsx';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\nimport {BAR_MIN_POINT_SIZE, barLabelValueOf} from '@/ui/metrics/barListLabels.js';\nimport {useChartColors} from '@/ui/metrics/chartParts.jsx';\n\nconst ROW_HEIGHT_PIXELS = 36;\n\n/**\n * El valor en la punta: el número fuerte y el detalle (\"de 8\") tenue; value es {value, detail} de barLabelValueOf. colors y\n * formatNumber: los de useChartColors y useFormatters (los da BarList: este pedazo lo pinta recharts por su cuenta).\n */\nfunction ValueLabel({x, y, width, height, value, colors, formatNumber}) {\n return (\n <text x={x + width + 8} y={y + height / 2} dominantBaseline=\"central\" fontSize={13}>\n <tspan fill={colors.text} fontWeight={600}>{formatNumber(value.value)}</tspan>\n {value.detail && <tspan fill={colors.muted} fontSize={12}>{` ${value.detail}`}</tspan>}\n </text>\n );\n}\n\n/**\n * @param {object} props\n * @param {Array<{key: string, label: string, value: number, detail?: string, tooltip?: string}>} props.items\n * @param {(item: any) => void} [props.onSelect] recibe el renglón de items que se picó\n * @param {string} props.emptyLabel ya traducido\n * @param {'primary'|'success'|'warning'|'error'|'info'} [props.tone]\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function BarList({items, onSelect, emptyLabel, tone = 'primary', texts, defaultView = CHART_VIEW.chart, onViewChange}) {\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n const colors = useChartColors();\n const {formatNumber} = useFormatters();\n\n // guard clause: sin datos se dice, no se pinta un eje vacío\n if (!items.length) {\n return <Typography variant=\"body2\" color=\"text.secondary\">{emptyLabel}</Typography>;\n }\n\n // lo más largo de la etiqueta decide el ancho del eje: sin esto el nombre se corta o sobra medio contenedor\n // OJO: String(... ?? '') porque un renglón sin nombre (catálogo dado de baja) tumbaba toda la gráfica\n // OJO: 220 px de tope. Con 160 se cortaban etiquetas largas («Cuenta pendiente de activar») sin puntos suspensivos\n // ni forma de leerlas; el tooltip de la barra sigue mostrando el texto completo\n const labelWidth = Math.min(220, 16 + Math.max(...items.map((item) => String(item.label ?? '').length)) * 7);\n const longestValue = Math.max(...items.map((item) => `${formatNumber(item.value)} ${item.detail ?? ''}`.length));\n\n return (\n <Box>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n {asTable ? (\n <Table size=\"small\">\n <TableBody>\n {items.map((item) => (\n <TableRow key={item.key} hover={Boolean(onSelect)} onClick={onSelect ? () => onSelect(item) : undefined}\n sx={{cursor: onSelect ? 'pointer' : 'default'}}>\n <TableCell>{item.label}</TableCell>\n <TableCell align=\"right\">{formatNumber(item.value)} {item.detail}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n ) : (\n <Box sx={{height: items.length * ROW_HEIGHT_PIXELS, color: `${tone}.main`}}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={items} layout=\"vertical\" margin={{top: 0, bottom: 0, left: 0, right: 16 + longestValue * 7}}>\n {/* OJO: con todo en 0 el dominio [0, 0] manda el 0 a la MITAD del eje (escala degenerada de d3) y la\n barra de 1 px con su «0 de 2» saldría a medio renglón; el tope mínimo de 1 lo deja en el origen */}\n <XAxis type=\"number\" hide domain={[0, (dataMax) => Math.max(dataMax, 1)]} />\n <YAxis type=\"category\" dataKey=\"label\" width={labelWidth} tickLine={false} axisLine={false}\n tick={{fill: colors.text, fontSize: 13}} />\n <Tooltip cursor={{fill: colors.hover}}\n content={<ChartTooltip render={(item) => item.tooltip ?? `${item.label}: ${formatNumber(item.value)}`} />} />\n <Bar dataKey=\"value\" fill=\"currentColor\" maxBarSize={16} radius={[0, 4, 4, 0]} isAnimationActive={false}\n minPointSize={BAR_MIN_POINT_SIZE} cursor={onSelect ? 'pointer' : 'default'}\n onClick={onSelect ? (entry) => onSelect(entry.payload) : undefined}>\n {/* OJO: SIN dataKey; con dataKey LabelList ignora valueAccessor y regresa el índice corrido */}\n <LabelList valueAccessor={barLabelValueOf} content={(labelProps) => <ValueLabel {...labelProps} colors={colors} formatNumber={formatNumber} />} />\n </Bar>\n </BarChart>\n </ResponsiveContainer>\n </Box>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BarList.js","sources":["../../../src/ui/metrics/BarList.jsx"],"sourcesContent":["// Barras horizontales de UNA serie con su nombre a la izquierda y su valor en la punta (ventas por producto,\n// cuentas por organización), dibujadas con Recharts.\n//\n// Horizontales porque los nombres son largos (\"Empresa / Área de ventas\"): se leen completos sin rotarlos. Una serie → un\n// color (el del tono, vía currentColor: los atributos SVG no leen var(...) pero sí currentColor); el valor va en tinta,\n// nunca del color de la barra; y cada barra puede llevar a la pantalla que la explica.\n//\n// OJO: el número y el detalle de la punta salen del renglón de la barra (barListLabels.js), nunca de items[index]: Recharts\n// descarta las barras de ancho 0 y renumera las etiquetas, y el detalle se corría al renglón de arriba.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaBarList con defaultProps y\n// styleOverrides de sus partes: row, chart.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Table from '@mui/material/Table';\nimport TableBody from '@mui/material/TableBody';\nimport TableCell from '@mui/material/TableCell';\nimport TableRow from '@mui/material/TableRow';\nimport Typography from '@mui/material/Typography';\nimport {Bar, BarChart, LabelList, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport ChartTooltip from '@/ui/metrics/ChartTooltip.jsx';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\nimport {BAR_MIN_POINT_SIZE, barLabelValueOf} from '@/ui/metrics/barListLabels.js';\nimport {useChartColors} from '@/ui/metrics/chartParts.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaBarList)\nconst THEME_NAME = 'CalcitaBarList';\nconst BarListRow = piecePart(THEME_NAME, 'Row', TableRow);\nconst BarListChart = piecePart(THEME_NAME, 'Chart', Box);\n\nconst ROW_HEIGHT_PIXELS = 36;\n\n/**\n * El valor en la punta: el número fuerte y el detalle (\"de 8\") tenue; value es {value, detail} de barLabelValueOf. colors y\n * formatNumber: los de useChartColors y useFormatters (los da BarList: este pedazo lo pinta recharts por su cuenta).\n */\nfunction ValueLabel({x, y, width, height, value, colors, formatNumber}) {\n return (\n <text x={x + width + 8} y={y + height / 2} dominantBaseline=\"central\" fontSize={13}>\n <tspan fill={colors.text} fontWeight={600}>{formatNumber(value.value)}</tspan>\n {value.detail && <tspan fill={colors.muted} fontSize={12}>{` ${value.detail}`}</tspan>}\n </text>\n );\n}\n\n/**\n * @param {object} props\n * @param {Array<{key: string, label: string, value: number, detail?: string, tooltip?: string}>} props.items\n * @param {(item: any) => void} [props.onSelect] recibe el renglón de items que se picó\n * @param {string} props.emptyLabel ya traducido\n * @param {'primary'|'success'|'warning'|'error'|'info'} [props.tone]\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function BarList(props) {\n // lo que el proyecto puso en su tema (components.CalcitaBarList.defaultProps) y encima lo que llega aquí\n const {items, onSelect, emptyLabel, tone = 'primary', texts, defaultView = CHART_VIEW.chart, onViewChange} = usePieceProps(props, THEME_NAME);\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n const colors = useChartColors();\n const {formatNumber} = useFormatters();\n\n // guard clause: sin datos se dice, no se pinta un eje vacío\n if (!items.length) {\n return <Typography variant=\"body2\" color=\"text.secondary\">{emptyLabel}</Typography>;\n }\n\n // lo más largo de la etiqueta decide el ancho del eje: sin esto el nombre se corta o sobra medio contenedor\n // OJO: String(... ?? '') porque un renglón sin nombre (catálogo dado de baja) tumbaba toda la gráfica\n // OJO: 220 px de tope. Con 160 se cortaban etiquetas largas («Cuenta pendiente de activar») sin puntos suspensivos\n // ni forma de leerlas; el tooltip de la barra sigue mostrando el texto completo\n const labelWidth = Math.min(220, 16 + Math.max(...items.map((item) => String(item.label ?? '').length)) * 7);\n const longestValue = Math.max(...items.map((item) => `${formatNumber(item.value)} ${item.detail ?? ''}`.length));\n\n return (\n <Box>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n {asTable ? (\n <Table size=\"small\">\n <TableBody>\n {items.map((item) => (\n <BarListRow key={item.key} hover={Boolean(onSelect)} onClick={onSelect ? () => onSelect(item) : undefined}\n ownSx={{cursor: onSelect ? 'pointer' : 'default'}}>\n <TableCell>{item.label}</TableCell>\n <TableCell align=\"right\">{formatNumber(item.value)} {item.detail}</TableCell>\n </BarListRow>\n ))}\n </TableBody>\n </Table>\n ) : (\n <BarListChart ownSx={{height: items.length * ROW_HEIGHT_PIXELS, color: `${tone}.main`}}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={items} layout=\"vertical\" margin={{top: 0, bottom: 0, left: 0, right: 16 + longestValue * 7}}>\n {/* OJO: con todo en 0 el dominio [0, 0] manda el 0 a la MITAD del eje (escala degenerada de d3) y la\n barra de 1 px con su «0 de 2» saldría a medio renglón; el tope mínimo de 1 lo deja en el origen */}\n <XAxis type=\"number\" hide domain={[0, (dataMax) => Math.max(dataMax, 1)]} />\n <YAxis type=\"category\" dataKey=\"label\" width={labelWidth} tickLine={false} axisLine={false}\n tick={{fill: colors.text, fontSize: 13}} />\n <Tooltip cursor={{fill: colors.hover}}\n content={<ChartTooltip render={(item) => item.tooltip ?? `${item.label}: ${formatNumber(item.value)}`} />} />\n <Bar dataKey=\"value\" fill=\"currentColor\" maxBarSize={16} radius={[0, 4, 4, 0]} isAnimationActive={false}\n minPointSize={BAR_MIN_POINT_SIZE} cursor={onSelect ? 'pointer' : 'default'}\n onClick={onSelect ? (entry) => onSelect(entry.payload) : undefined}>\n {/* OJO: SIN dataKey; con dataKey LabelList ignora valueAccessor y regresa el índice corrido */}\n <LabelList valueAccessor={barLabelValueOf} content={(labelProps) => <ValueLabel {...labelProps} colors={colors} formatNumber={formatNumber} />} />\n </Bar>\n </BarChart>\n </ResponsiveContainer>\n </BarListChart>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -14,6 +14,24 @@ import Typography from "@mui/material/Typography";
14
14
  import { useFormatters } from "../../toolkit/useFormatters.js";
15
15
  import { calendarWeeksOf, levelOf, HEATMAP_LEVELS } from "./heatmapScale.js";
16
16
  import TableToggle, { CHART_VIEW } from "./TableToggle.js";
17
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
18
+ const THEME_NAME = "CalcitaCalendarHeatmap";
19
+ const HeatmapHeader = piecePart(THEME_NAME, "Header", Stack);
20
+ const HeatmapToggle = piecePart(THEME_NAME, "Toggle", Box);
21
+ const HeatmapTableArea = piecePart(THEME_NAME, "TableArea", Box);
22
+ const HeatmapDateCell = piecePart(THEME_NAME, "DateCell", TableCell);
23
+ const HeatmapValueCell = piecePart(THEME_NAME, "ValueCell", TableCell);
24
+ const HeatmapDescriptionCell = piecePart(THEME_NAME, "DescriptionCell", TableCell);
25
+ const HeatmapGridArea = piecePart(THEME_NAME, "GridArea", Box);
26
+ const HeatmapGrid = piecePart(THEME_NAME, "Grid", Box);
27
+ const HeatmapMonthLabel = piecePart(THEME_NAME, "MonthLabel", Typography);
28
+ const HeatmapWeek = piecePart(THEME_NAME, "Week", Box);
29
+ const HeatmapDayLabel = piecePart(THEME_NAME, "DayLabel", Typography);
30
+ const HeatmapCell = piecePart(THEME_NAME, "Cell", Box);
31
+ const HeatmapLegend = piecePart(THEME_NAME, "Legend", Stack);
32
+ const HeatmapLegendLess = piecePart(THEME_NAME, "LegendLess", Typography);
33
+ const HeatmapLegendCell = piecePart(THEME_NAME, "LegendCell", Box);
34
+ const HeatmapLegendMore = piecePart(THEME_NAME, "LegendMore", Typography);
17
35
  const CELL_PIXELS = { xs: 12, md: 16 };
18
36
  const GAP_PIXELS = 3;
19
37
  const LABELED_WEEKDAYS = /* @__PURE__ */ new Set([1, 3, 5]);
@@ -25,7 +43,8 @@ function levelFill(theme, tone, level) {
25
43
  }
26
44
  return `color-mix(in srgb, ${palette[tone].main} ${LEVEL_TONE_PERCENT[level]}%, transparent)`;
27
45
  }
28
- function CalendarHeatmap({ startsOn, endsOn, days, ariaLabel, valueLabel, describeValue, summary, emptyLabel, tone = "primary", texts, defaultView = CHART_VIEW.chart, onViewChange }) {
46
+ function CalendarHeatmap(props) {
47
+ const { startsOn, endsOn, days, ariaLabel, valueLabel, describeValue, summary, emptyLabel, tone = "primary", texts, defaultView = CHART_VIEW.chart, onViewChange } = usePieceProps(props, THEME_NAME);
29
48
  const { t } = useToolkitTranslation("common", texts);
30
49
  const { formatDate, formatMonthShortName, formatNumber, formatWeekdayShortName } = useFormatters();
31
50
  const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);
@@ -36,38 +55,38 @@ function CalendarHeatmap({ startsOn, endsOn, days, ariaLabel, valueLabel, descri
36
55
  const { weeks, monthMarks, thresholds } = useMemo(() => calendarWeeksOf({ startsOn, endsOn, days }), [startsOn, endsOn, days]);
37
56
  const activeDays = days.filter((day) => day.value > 0);
38
57
  return /* @__PURE__ */ jsxs(Box, { children: [
39
- /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, sx: { justifyContent: "space-between", alignItems: "center", mb: 1 }, children: [
58
+ /* @__PURE__ */ jsxs(HeatmapHeader, { direction: "row", spacing: 2, ownSx: { justifyContent: "space-between", alignItems: "center", mb: 1 }, children: [
40
59
  /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: activeDays.length ? summary : emptyLabel }),
41
- /* @__PURE__ */ jsx(Box, { sx: { flexShrink: 0 }, children: /* @__PURE__ */ jsx(TableToggle, { asTable, onToggle: toggleView, texts }) })
60
+ /* @__PURE__ */ jsx(HeatmapToggle, { ownSx: { flexShrink: 0 }, children: /* @__PURE__ */ jsx(TableToggle, { asTable, onToggle: toggleView, texts }) })
42
61
  ] }),
43
- asTable ? /* @__PURE__ */ jsx(Box, { sx: { maxHeight: 260, overflowY: "auto" }, children: /* @__PURE__ */ jsxs(Table, { size: "small", "aria-label": ariaLabel, children: [
62
+ asTable ? /* @__PURE__ */ jsx(HeatmapTableArea, { ownSx: { maxHeight: 260, overflowY: "auto" }, children: /* @__PURE__ */ jsxs(Table, { size: "small", "aria-label": ariaLabel, children: [
44
63
  /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
45
64
  /* @__PURE__ */ jsx(TableCell, { children: t("charts.day") }),
46
65
  /* @__PURE__ */ jsx(TableCell, { align: "right", children: valueLabel }),
47
66
  /* @__PURE__ */ jsx(TableCell, {})
48
67
  ] }) }),
49
68
  /* @__PURE__ */ jsx(TableBody, { children: [...activeDays].reverse().map((day) => /* @__PURE__ */ jsxs(TableRow, { children: [
50
- /* @__PURE__ */ jsx(TableCell, { sx: { whiteSpace: "nowrap" }, children: formatDate(day.date) }),
51
- /* @__PURE__ */ jsx(TableCell, { align: "right", sx: { fontVariantNumeric: "tabular-nums" }, children: formatNumber(day.value) }),
52
- /* @__PURE__ */ jsx(TableCell, { sx: { color: "text.secondary" }, children: day.detail })
69
+ /* @__PURE__ */ jsx(HeatmapDateCell, { ownSx: { whiteSpace: "nowrap" }, children: formatDate(day.date) }),
70
+ /* @__PURE__ */ jsx(HeatmapValueCell, { align: "right", ownSx: { fontVariantNumeric: "tabular-nums" }, children: formatNumber(day.value) }),
71
+ /* @__PURE__ */ jsx(HeatmapDescriptionCell, { ownSx: { color: "text.secondary" }, children: day.detail })
53
72
  ] }, day.date)) })
54
73
  ] }) }) : (
55
74
  // el calendario no se encoge: en pantallas angostas se desliza y arranca mostrando lo más reciente
56
75
  /* @__PURE__ */ jsx(
57
- Box,
76
+ HeatmapGridArea,
58
77
  {
59
- sx: { overflowX: "auto", pb: 0.5 },
78
+ ownSx: { overflowX: "auto", pb: 0.5 },
60
79
  ref: (node) => {
61
80
  if (node) {
62
81
  node.scrollLeft = node.scrollWidth;
63
82
  }
64
83
  },
65
84
  children: /* @__PURE__ */ jsxs(
66
- Box,
85
+ HeatmapGrid,
67
86
  {
68
87
  role: "img",
69
88
  "aria-label": ariaLabel,
70
- sx: {
89
+ ownSx: {
71
90
  display: "inline-grid",
72
91
  gridTemplateColumns: {
73
92
  xs: `auto repeat(${weeks.length}, ${CELL_PIXELS.xs}px)`,
@@ -80,22 +99,22 @@ function CalendarHeatmap({ startsOn, endsOn, days, ariaLabel, valueLabel, descri
80
99
  children: [
81
100
  /* @__PURE__ */ jsx(Box, {}),
82
101
  monthMarks.map((month, column) => /* @__PURE__ */ jsx(
83
- Typography,
102
+ HeatmapMonthLabel,
84
103
  {
85
104
  variant: "caption",
86
105
  color: "text.secondary",
87
- sx: { fontSize: 10, lineHeight: 1, whiteSpace: "nowrap", overflow: "visible", width: CELL_PIXELS },
106
+ ownSx: { fontSize: 10, lineHeight: 1, whiteSpace: "nowrap", overflow: "visible", width: CELL_PIXELS },
88
107
  children: month ? formatMonthShortName(month) : ""
89
108
  },
90
109
  `month-${column}`
91
110
  )),
92
- [1, 2, 3, 4, 5, 6, 7].map((isoWeekday) => /* @__PURE__ */ jsxs(Box, { sx: { display: "contents" }, children: [
111
+ [1, 2, 3, 4, 5, 6, 7].map((isoWeekday) => /* @__PURE__ */ jsxs(HeatmapWeek, { ownSx: { display: "contents" }, children: [
93
112
  /* @__PURE__ */ jsx(
94
- Typography,
113
+ HeatmapDayLabel,
95
114
  {
96
115
  variant: "caption",
97
116
  color: "text.secondary",
98
- sx: { fontSize: 10, lineHeight: { xs: `${CELL_PIXELS.xs}px`, md: `${CELL_PIXELS.md}px` }, pr: 0.75 },
117
+ ownSx: { fontSize: 10, lineHeight: { xs: `${CELL_PIXELS.xs}px`, md: `${CELL_PIXELS.md}px` }, pr: 0.75 },
99
118
  children: LABELED_WEEKDAYS.has(isoWeekday) ? formatWeekdayShortName(isoWeekday) : ""
100
119
  }
101
120
  ),
@@ -111,7 +130,7 @@ function CalendarHeatmap({ startsOn, endsOn, days, ariaLabel, valueLabel, descri
111
130
  arrow: true,
112
131
  disableInteractive: true,
113
132
  title: `${formatDate(day.date)}: ${describeValue(day.value)}${day.detail ? ` · ${day.detail}` : ""}`,
114
- children: /* @__PURE__ */ jsx(Box, { sx: (theme) => ({ width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: "3px", bgcolor: levelFill(theme, tone, level) }) })
133
+ children: /* @__PURE__ */ jsx(HeatmapCell, { ownSx: (theme) => ({ width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: "3px", bgcolor: levelFill(theme, tone, level) }) })
115
134
  },
116
135
  day.date
117
136
  );
@@ -123,10 +142,10 @@ function CalendarHeatmap({ startsOn, endsOn, days, ariaLabel, valueLabel, descri
123
142
  }
124
143
  )
125
144
  ),
126
- !asTable && /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.5, sx: { alignItems: "center", justifyContent: "flex-end", mt: 1 }, "aria-hidden": "true", children: [
127
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", sx: { mr: 0.5 }, children: t("charts.less") }),
128
- HEATMAP_LEVELS.map((level) => /* @__PURE__ */ jsx(Box, { sx: (theme) => ({ width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: "3px", bgcolor: levelFill(theme, tone, level) }) }, level)),
129
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", sx: { ml: 0.5 }, children: t("charts.more") })
145
+ !asTable && /* @__PURE__ */ jsxs(HeatmapLegend, { direction: "row", spacing: 0.5, ownSx: { alignItems: "center", justifyContent: "flex-end", mt: 1 }, "aria-hidden": "true", children: [
146
+ /* @__PURE__ */ jsx(HeatmapLegendLess, { variant: "caption", color: "text.secondary", ownSx: { mr: 0.5 }, children: t("charts.less") }),
147
+ HEATMAP_LEVELS.map((level) => /* @__PURE__ */ jsx(HeatmapLegendCell, { ownSx: (theme) => ({ width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: "3px", bgcolor: levelFill(theme, tone, level) }) }, level)),
148
+ /* @__PURE__ */ jsx(HeatmapLegendMore, { variant: "caption", color: "text.secondary", ownSx: { ml: 0.5 }, children: t("charts.more") })
130
149
  ] })
131
150
  ] });
132
151
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CalendarHeatmap.js","sources":["../../../src/ui/metrics/CalendarHeatmap.jsx"],"sourcesContent":["// Calendario de actividad: un cuadro por día, semanas en columnas (el de GitHub).\n//\n// Sirve para ver RITMO de un vistazo: qué días llegan cargas, si hubo semanas muertas, si la actividad crece. Las\n// reglas de visualización:\n// - es MAGNITUD, así que va un solo tono de claro a oscuro (el del tono que se pida), en cuatro niveles más \"sin\n// actividad\". Nunca un arcoíris. Se arma con color-mix sobre el color del tema (su variable CSS si el tema las usa),\n// sin hexadecimales: en modo oscuro los mismos niveles se ven sobre su propia superficie;\n// - los niveles se cortan por CUARTILES de los días con actividad (heatmapScale.js), no por valores fijos;\n// - leyenda \"Menos → Más\", tooltip por día con el número exacto (el color solo nunca dice cuánto) y VISTA DE TABLA\n// (para lector de pantalla, para quien no distingue el tono y para copiar los números).\n//\n// Sin librería a propósito: el Heatmap de MUI X Charts es de la edición Pro, que pide licencia.\n//\n// Textos por props y del paquete, y fechas con los formatos del paquete.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useMemo, useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport Table from '@mui/material/Table';\nimport TableBody from '@mui/material/TableBody';\nimport TableCell from '@mui/material/TableCell';\nimport TableHead from '@mui/material/TableHead';\nimport TableRow from '@mui/material/TableRow';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {HEATMAP_LEVELS, calendarWeeksOf, levelOf} from '@/ui/metrics/heatmapScale.js';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\n\n// cuadros de 12 px en teléfono (el calendario se desliza) y de 16 px desde md, donde el panel ocupa todo el ancho\nconst CELL_PIXELS = {xs: 12, md: 16};\nconst GAP_PIXELS = 3;\n// solo lunes, miércoles y viernes llevan rótulo: los siete encimados no se leen a 12 px\nconst LABELED_WEEKDAYS = new Set([1, 3, 5]);\n// porcentaje del tono en cada nivel; el nivel 0 es el gris de \"hover\" del tema\nconst LEVEL_TONE_PERCENT = {1: 30, 2: 55, 3: 78, 4: 100};\n\n/**\n * Relleno de un nivel con los colores del tema.\n *\n * @param {object} theme tema de MUI (con o sin variables CSS)\n * @param {string} tone primary, info, success...\n * @param {number} level 0 a 4\n * @returns {string} color CSS\n */\nfunction levelFill(theme, tone, level) {\n // un tema con variables CSS las trae en theme.vars; el tema por omisión de MUI, solo en theme.palette\n const {palette} = theme.vars ?? theme;\n if (level === 0) {\n return palette.action.hover;\n }\n return `color-mix(in srgb, ${palette[tone].main} ${LEVEL_TONE_PERCENT[level]}%, transparent)`;\n}\n\n/**\n * @param {object} props\n * @param {string} props.startsOn primer día del rango (\"2025-09-16\"), fecha de calendario\n * @param {string} props.endsOn último día del rango (\"2026-09-15\")\n * @param {Array<{date: string, value: number, detail?: string}>} props.days solo los días con actividad; el resto vale\n * 0\n * @param {string} props.ariaLabel qué muestra el calendario, ya traducido\n * @param {string} props.valueLabel encabezado de la columna de valor en la tabla (\"Registros leídos\")\n * @param {(value: number) => string} props.describeValue el valor en palabras para el tooltip (\"120 registros leídos\")\n * @param {import('react').ReactNode} [props.summary] renglón de resumen arriba del calendario\n * @param {string} [props.emptyLabel] qué decir si ningún día tiene actividad\n * @param {'primary'|'info'|'success'|'warning'|'error'} [props.tone]\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function CalendarHeatmap({startsOn, endsOn, days, ariaLabel, valueLabel, describeValue, summary, emptyLabel, tone = 'primary', texts, defaultView = CHART_VIEW.chart, onViewChange}) {\n const {t} = useToolkitTranslation('common', texts);\n const {formatDate, formatMonthShortName, formatNumber, formatWeekdayShortName} = useFormatters();\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n\n const {weeks, monthMarks, thresholds} = useMemo(() => calendarWeeksOf({startsOn, endsOn, days}), [startsOn, endsOn, days]);\n const activeDays = days.filter((day) => day.value > 0);\n\n return (\n <Box>\n <Stack direction=\"row\" spacing={2} sx={{justifyContent: 'space-between', alignItems: 'center', mb: 1}}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {activeDays.length ? summary : emptyLabel}\n </Typography>\n <Box sx={{flexShrink: 0}}>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n </Box>\n </Stack>\n\n {asTable ? (\n <Box sx={{maxHeight: 260, overflowY: 'auto'}}>\n <Table size=\"small\" aria-label={ariaLabel}>\n <TableHead>\n <TableRow>\n <TableCell>{t('charts.day')}</TableCell>\n <TableCell align=\"right\">{valueLabel}</TableCell>\n <TableCell />\n </TableRow>\n </TableHead>\n <TableBody>\n {[...activeDays].reverse().map((day) => (\n <TableRow key={day.date}>\n <TableCell sx={{whiteSpace: 'nowrap'}}>{formatDate(day.date)}</TableCell>\n <TableCell align=\"right\" sx={{fontVariantNumeric: 'tabular-nums'}}>{formatNumber(day.value)}</TableCell>\n <TableCell sx={{color: 'text.secondary'}}>{day.detail}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </Box>\n ) : (\n // el calendario no se encoge: en pantallas angostas se desliza y arranca mostrando lo más reciente\n <Box sx={{overflowX: 'auto', pb: 0.5}}\n ref={(node) => {\n if (node) {\n node.scrollLeft = node.scrollWidth;\n }\n }}>\n <Box role=\"img\" aria-label={ariaLabel}\n sx={{\n display: 'inline-grid',\n gridTemplateColumns: {\n xs: `auto repeat(${weeks.length}, ${CELL_PIXELS.xs}px)`,\n md: `auto repeat(${weeks.length}, ${CELL_PIXELS.md}px)`,\n },\n columnGap: `${GAP_PIXELS}px`,\n rowGap: `${GAP_PIXELS}px`,\n alignItems: 'center',\n }}>\n <Box />\n {monthMarks.map((month, column) => (\n <Typography key={`month-${column}`} variant=\"caption\" color=\"text.secondary\"\n sx={{fontSize: 10, lineHeight: 1, whiteSpace: 'nowrap', overflow: 'visible', width: CELL_PIXELS}}>\n {month ? formatMonthShortName(month) : ''}\n </Typography>\n ))}\n {[1, 2, 3, 4, 5, 6, 7].map((isoWeekday) => (\n <Box key={`weekday-${isoWeekday}`} sx={{display: 'contents'}}>\n <Typography variant=\"caption\" color=\"text.secondary\"\n sx={{fontSize: 10, lineHeight: {xs: `${CELL_PIXELS.xs}px`, md: `${CELL_PIXELS.md}px`}, pr: 0.75}}>\n {LABELED_WEEKDAYS.has(isoWeekday) ? formatWeekdayShortName(isoWeekday) : ''}\n </Typography>\n {weeks.map((week, column) => {\n const day = week[isoWeekday - 1];\n if (!day) {\n return <Box key={`outside-${column}-${isoWeekday}`} />;\n }\n const level = levelOf(day.value, thresholds);\n return (\n <Tooltip key={day.date} arrow disableInteractive\n title={`${formatDate(day.date)}: ${describeValue(day.value)}${day.detail ? ` · ${day.detail}` : ''}`}>\n <Box sx={(theme) => ({width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: '3px', bgcolor: levelFill(theme, tone, level)})} />\n </Tooltip>\n );\n })}\n </Box>\n ))}\n </Box>\n </Box>\n )}\n\n {!asTable && (\n <Stack direction=\"row\" spacing={0.5} sx={{alignItems: 'center', justifyContent: 'flex-end', mt: 1}} aria-hidden=\"true\">\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{mr: 0.5}}>{t('charts.less')}</Typography>\n {HEATMAP_LEVELS.map((level) => (\n <Box key={level} sx={(theme) => ({width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: '3px', bgcolor: levelFill(theme, tone, level)})} />\n ))}\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ml: 0.5}}>{t('charts.more')}</Typography>\n </Stack>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CalendarHeatmap.js","sources":["../../../src/ui/metrics/CalendarHeatmap.jsx"],"sourcesContent":["// Calendario de actividad: un cuadro por día, semanas en columnas (el de GitHub).\n//\n// Sirve para ver RITMO de un vistazo: qué días llegan cargas, si hubo semanas muertas, si la actividad crece. Las\n// reglas de visualización:\n// - es MAGNITUD, así que va un solo tono de claro a oscuro (el del tono que se pida), en cuatro niveles más \"sin\n// actividad\". Nunca un arcoíris. Se arma con color-mix sobre el color del tema (su variable CSS si el tema las usa),\n// sin hexadecimales: en modo oscuro los mismos niveles se ven sobre su propia superficie;\n// - los niveles se cortan por CUARTILES de los días con actividad (heatmapScale.js), no por valores fijos;\n// - leyenda \"Menos → Más\", tooltip por día con el número exacto (el color solo nunca dice cuánto) y VISTA DE TABLA\n// (para lector de pantalla, para quien no distingue el tono y para copiar los números).\n//\n// Sin librería a propósito: el Heatmap de MUI X Charts es de la edición Pro, que pide licencia.\n//\n// Textos por props y del paquete, y fechas con los formatos del paquete.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaCalendarHeatmap con defaultProps y\n// styleOverrides de sus partes: header, toggle, tableArea, dateCell, valueCell, descriptionCell, gridArea, grid,\n// monthLabel, week, dayLabel, cell, legend, legendLess, legendCell, legendMore.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useMemo, useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport Table from '@mui/material/Table';\nimport TableBody from '@mui/material/TableBody';\nimport TableCell from '@mui/material/TableCell';\nimport TableHead from '@mui/material/TableHead';\nimport TableRow from '@mui/material/TableRow';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {HEATMAP_LEVELS, calendarWeeksOf, levelOf} from '@/ui/metrics/heatmapScale.js';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaCalendarHeatmap)\nconst THEME_NAME = 'CalcitaCalendarHeatmap';\nconst HeatmapHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst HeatmapToggle = piecePart(THEME_NAME, 'Toggle', Box);\nconst HeatmapTableArea = piecePart(THEME_NAME, 'TableArea', Box);\nconst HeatmapDateCell = piecePart(THEME_NAME, 'DateCell', TableCell);\nconst HeatmapValueCell = piecePart(THEME_NAME, 'ValueCell', TableCell);\nconst HeatmapDescriptionCell = piecePart(THEME_NAME, 'DescriptionCell', TableCell);\nconst HeatmapGridArea = piecePart(THEME_NAME, 'GridArea', Box);\nconst HeatmapGrid = piecePart(THEME_NAME, 'Grid', Box);\nconst HeatmapMonthLabel = piecePart(THEME_NAME, 'MonthLabel', Typography);\nconst HeatmapWeek = piecePart(THEME_NAME, 'Week', Box);\nconst HeatmapDayLabel = piecePart(THEME_NAME, 'DayLabel', Typography);\nconst HeatmapCell = piecePart(THEME_NAME, 'Cell', Box);\nconst HeatmapLegend = piecePart(THEME_NAME, 'Legend', Stack);\nconst HeatmapLegendLess = piecePart(THEME_NAME, 'LegendLess', Typography);\nconst HeatmapLegendCell = piecePart(THEME_NAME, 'LegendCell', Box);\nconst HeatmapLegendMore = piecePart(THEME_NAME, 'LegendMore', Typography);\n\n// cuadros de 12 px en teléfono (el calendario se desliza) y de 16 px desde md, donde el panel ocupa todo el ancho\nconst CELL_PIXELS = {xs: 12, md: 16};\nconst GAP_PIXELS = 3;\n// solo lunes, miércoles y viernes llevan rótulo: los siete encimados no se leen a 12 px\nconst LABELED_WEEKDAYS = new Set([1, 3, 5]);\n// porcentaje del tono en cada nivel; el nivel 0 es el gris de \"hover\" del tema\nconst LEVEL_TONE_PERCENT = {1: 30, 2: 55, 3: 78, 4: 100};\n\n/**\n * Relleno de un nivel con los colores del tema.\n *\n * @param {object} theme tema de MUI (con o sin variables CSS)\n * @param {string} tone primary, info, success...\n * @param {number} level 0 a 4\n * @returns {string} color CSS\n */\nfunction levelFill(theme, tone, level) {\n // un tema con variables CSS las trae en theme.vars; el tema por omisión de MUI, solo en theme.palette\n const {palette} = theme.vars ?? theme;\n if (level === 0) {\n return palette.action.hover;\n }\n return `color-mix(in srgb, ${palette[tone].main} ${LEVEL_TONE_PERCENT[level]}%, transparent)`;\n}\n\n/**\n * @param {object} props\n * @param {string} props.startsOn primer día del rango (\"2025-09-16\"), fecha de calendario\n * @param {string} props.endsOn último día del rango (\"2026-09-15\")\n * @param {Array<{date: string, value: number, detail?: string}>} props.days solo los días con actividad; el resto vale\n * 0\n * @param {string} props.ariaLabel qué muestra el calendario, ya traducido\n * @param {string} props.valueLabel encabezado de la columna de valor en la tabla (\"Registros leídos\")\n * @param {(value: number) => string} props.describeValue el valor en palabras para el tooltip (\"120 registros leídos\")\n * @param {import('react').ReactNode} [props.summary] renglón de resumen arriba del calendario\n * @param {string} [props.emptyLabel] qué decir si ningún día tiene actividad\n * @param {'primary'|'info'|'success'|'warning'|'error'} [props.tone]\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function CalendarHeatmap(props) {\n // lo que el proyecto puso en su tema (components.CalcitaCalendarHeatmap.defaultProps) y encima lo que llega aquí\n const {startsOn, endsOn, days, ariaLabel, valueLabel, describeValue, summary, emptyLabel, tone = 'primary', texts, defaultView = CHART_VIEW.chart, onViewChange} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('common', texts);\n const {formatDate, formatMonthShortName, formatNumber, formatWeekdayShortName} = useFormatters();\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n\n const {weeks, monthMarks, thresholds} = useMemo(() => calendarWeeksOf({startsOn, endsOn, days}), [startsOn, endsOn, days]);\n const activeDays = days.filter((day) => day.value > 0);\n\n return (\n <Box>\n <HeatmapHeader direction=\"row\" spacing={2} ownSx={{justifyContent: 'space-between', alignItems: 'center', mb: 1}}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {activeDays.length ? summary : emptyLabel}\n </Typography>\n <HeatmapToggle ownSx={{flexShrink: 0}}>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n </HeatmapToggle>\n </HeatmapHeader>\n\n {asTable ? (\n <HeatmapTableArea ownSx={{maxHeight: 260, overflowY: 'auto'}}>\n <Table size=\"small\" aria-label={ariaLabel}>\n <TableHead>\n <TableRow>\n <TableCell>{t('charts.day')}</TableCell>\n <TableCell align=\"right\">{valueLabel}</TableCell>\n <TableCell />\n </TableRow>\n </TableHead>\n <TableBody>\n {[...activeDays].reverse().map((day) => (\n <TableRow key={day.date}>\n <HeatmapDateCell ownSx={{whiteSpace: 'nowrap'}}>{formatDate(day.date)}</HeatmapDateCell>\n <HeatmapValueCell align=\"right\" ownSx={{fontVariantNumeric: 'tabular-nums'}}>{formatNumber(day.value)}</HeatmapValueCell>\n <HeatmapDescriptionCell ownSx={{color: 'text.secondary'}}>{day.detail}</HeatmapDescriptionCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </HeatmapTableArea>\n ) : (\n // el calendario no se encoge: en pantallas angostas se desliza y arranca mostrando lo más reciente\n <HeatmapGridArea ownSx={{overflowX: 'auto', pb: 0.5}}\n ref={(node) => {\n if (node) {\n node.scrollLeft = node.scrollWidth;\n }\n }}>\n <HeatmapGrid role=\"img\" aria-label={ariaLabel}\n ownSx={{\n display: 'inline-grid',\n gridTemplateColumns: {\n xs: `auto repeat(${weeks.length}, ${CELL_PIXELS.xs}px)`,\n md: `auto repeat(${weeks.length}, ${CELL_PIXELS.md}px)`,\n },\n columnGap: `${GAP_PIXELS}px`,\n rowGap: `${GAP_PIXELS}px`,\n alignItems: 'center',\n }}>\n <Box />\n {monthMarks.map((month, column) => (\n <HeatmapMonthLabel key={`month-${column}`} variant=\"caption\" color=\"text.secondary\"\n ownSx={{fontSize: 10, lineHeight: 1, whiteSpace: 'nowrap', overflow: 'visible', width: CELL_PIXELS}}>\n {month ? formatMonthShortName(month) : ''}\n </HeatmapMonthLabel>\n ))}\n {[1, 2, 3, 4, 5, 6, 7].map((isoWeekday) => (\n <HeatmapWeek key={`weekday-${isoWeekday}`} ownSx={{display: 'contents'}}>\n <HeatmapDayLabel variant=\"caption\" color=\"text.secondary\"\n ownSx={{fontSize: 10, lineHeight: {xs: `${CELL_PIXELS.xs}px`, md: `${CELL_PIXELS.md}px`}, pr: 0.75}}>\n {LABELED_WEEKDAYS.has(isoWeekday) ? formatWeekdayShortName(isoWeekday) : ''}\n </HeatmapDayLabel>\n {weeks.map((week, column) => {\n const day = week[isoWeekday - 1];\n if (!day) {\n return <Box key={`outside-${column}-${isoWeekday}`} />;\n }\n const level = levelOf(day.value, thresholds);\n return (\n <Tooltip key={day.date} arrow disableInteractive\n title={`${formatDate(day.date)}: ${describeValue(day.value)}${day.detail ? ` · ${day.detail}` : ''}`}>\n <HeatmapCell ownSx={(theme) => ({width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: '3px', bgcolor: levelFill(theme, tone, level)})} />\n </Tooltip>\n );\n })}\n </HeatmapWeek>\n ))}\n </HeatmapGrid>\n </HeatmapGridArea>\n )}\n\n {!asTable && (\n <HeatmapLegend direction=\"row\" spacing={0.5} ownSx={{alignItems: 'center', justifyContent: 'flex-end', mt: 1}} aria-hidden=\"true\">\n <HeatmapLegendLess variant=\"caption\" color=\"text.secondary\" ownSx={{mr: 0.5}}>{t('charts.less')}</HeatmapLegendLess>\n {HEATMAP_LEVELS.map((level) => (\n <HeatmapLegendCell key={level} ownSx={(theme) => ({width: CELL_PIXELS, height: CELL_PIXELS, borderRadius: '3px', bgcolor: levelFill(theme, tone, level)})} />\n ))}\n <HeatmapLegendMore variant=\"caption\" color=\"text.secondary\" ownSx={{ml: 0.5}}>{t('charts.more')}</HeatmapLegendMore>\n </HeatmapLegend>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAsCA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,UAAU,KAAK;AAC3D,MAAM,gBAAgB,UAAU,YAAY,UAAU,GAAG;AACzD,MAAM,mBAAmB,UAAU,YAAY,aAAa,GAAG;AAC/D,MAAM,kBAAkB,UAAU,YAAY,YAAY,SAAS;AACnE,MAAM,mBAAmB,UAAU,YAAY,aAAa,SAAS;AACrE,MAAM,yBAAyB,UAAU,YAAY,mBAAmB,SAAS;AACjF,MAAM,kBAAkB,UAAU,YAAY,YAAY,GAAG;AAC7D,MAAM,cAAc,UAAU,YAAY,QAAQ,GAAG;AACrD,MAAM,oBAAoB,UAAU,YAAY,cAAc,UAAU;AACxE,MAAM,cAAc,UAAU,YAAY,QAAQ,GAAG;AACrD,MAAM,kBAAkB,UAAU,YAAY,YAAY,UAAU;AACpE,MAAM,cAAc,UAAU,YAAY,QAAQ,GAAG;AACrD,MAAM,gBAAgB,UAAU,YAAY,UAAU,KAAK;AAC3D,MAAM,oBAAoB,UAAU,YAAY,cAAc,UAAU;AACxE,MAAM,oBAAoB,UAAU,YAAY,cAAc,GAAG;AACjE,MAAM,oBAAoB,UAAU,YAAY,cAAc,UAAU;AAGxE,MAAM,cAAc,EAAC,IAAI,IAAI,IAAI,GAAA;AACjC,MAAM,aAAa;AAEnB,MAAM,mBAAmB,oBAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;AAE1C,MAAM,qBAAqB,EAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAA;AAUpD,SAAS,UAAU,OAAO,MAAM,OAAO;AAEnC,QAAM,EAAC,QAAA,IAAW,MAAM,QAAQ;AAChC,MAAI,UAAU,GAAG;AACb,WAAO,QAAQ,OAAO;AAAA,EAC1B;AACA,SAAO,sBAAsB,QAAQ,IAAI,EAAE,IAAI,IAAI,mBAAmB,KAAK,CAAC;AAChF;AAkBA,SAAwB,gBAAgB,OAAO;AAE3C,QAAM,EAAC,UAAU,QAAQ,MAAM,WAAW,YAAY,eAAe,SAAS,YAAY,OAAO,WAAW,OAAO,cAAc,WAAW,OAAO,iBAAgB,cAAc,OAAO,UAAU;AAClM,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,EAAC,YAAY,sBAAsB,cAAc,uBAAA,IAA0B,cAAA;AACjF,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,gBAAgB,WAAW,KAAK;AACvE,QAAM,aAAa,MAAM;AACrB,eAAW,CAAC,OAAO;AACnB,mBAAe,UAAU,WAAW,QAAQ,WAAW,KAAK;AAAA,EAChE;AAEA,QAAM,EAAC,OAAO,YAAY,eAAc,QAAQ,MAAM,gBAAgB,EAAC,UAAU,QAAQ,MAAK,GAAG,CAAC,UAAU,QAAQ,IAAI,CAAC;AACzH,QAAM,aAAa,KAAK,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;AAErD,8BACK,KAAA,EACG,UAAA;AAAA,IAAA,qBAAC,eAAA,EAAc,WAAU,OAAM,SAAS,GAAG,OAAO,EAAC,gBAAgB,iBAAiB,YAAY,UAAU,IAAI,KAC1G,UAAA;AAAA,MAAA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,kBAC7B,UAAA,WAAW,SAAS,UAAU,WAAA,CACnC;AAAA,MACA,oBAAC,eAAA,EAAc,OAAO,EAAC,YAAY,EAAA,GAC/B,UAAA,oBAAC,aAAA,EAAY,SAAkB,UAAU,YAAY,OAAc,EAAA,CACvE;AAAA,IAAA,GACJ;AAAA,IAEC,UACG,oBAAC,kBAAA,EAAiB,OAAO,EAAC,WAAW,KAAK,WAAW,OAAA,GACjD,UAAA,qBAAC,OAAA,EAAM,MAAK,SAAQ,cAAY,WAC5B,UAAA;AAAA,MAAA,oBAAC,WAAA,EACG,+BAAC,UAAA,EACG,UAAA;AAAA,QAAA,oBAAC,WAAA,EAAW,UAAA,EAAE,YAAY,EAAA,CAAE;AAAA,QAC5B,oBAAC,WAAA,EAAU,OAAM,SAAS,UAAA,YAAW;AAAA,4BACpC,WAAA,CAAA,CAAU;AAAA,MAAA,EAAA,CACf,EAAA,CACJ;AAAA,MACA,oBAAC,WAAA,EACI,UAAA,CAAC,GAAG,UAAU,EAAE,UAAU,IAAI,CAAC,QAC5B,qBAAC,UAAA,EACG,UAAA;AAAA,QAAA,oBAAC,iBAAA,EAAgB,OAAO,EAAC,YAAY,YAAY,UAAA,WAAW,IAAI,IAAI,EAAA,CAAE;AAAA,QACtE,oBAAC,kBAAA,EAAiB,OAAM,SAAQ,OAAO,EAAC,oBAAoB,eAAA,GAAkB,UAAA,aAAa,IAAI,KAAK,EAAA,CAAE;AAAA,QACtG,oBAAC,0BAAuB,OAAO,EAAC,OAAO,oBAAoB,cAAI,OAAA,CAAO;AAAA,MAAA,KAH3D,IAAI,IAInB,CACH,EAAA,CACL;AAAA,IAAA,EAAA,CACJ,EAAA,CACJ;AAAA;AAAA,MAGA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAgB,OAAO,EAAC,WAAW,QAAQ,IAAI,IAAA;AAAA,UAC3C,KAAK,CAAC,SAAS;AACX,gBAAI,MAAM;AACN,mBAAK,aAAa,KAAK;AAAA,YAC3B;AAAA,UACJ;AAAA,UACD,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cAAY,MAAK;AAAA,cAAM,cAAY;AAAA,cAC/B,OAAO;AAAA,gBACH,SAAS;AAAA,gBACT,qBAAqB;AAAA,kBACjB,IAAI,eAAe,MAAM,MAAM,KAAK,YAAY,EAAE;AAAA,kBAClD,IAAI,eAAe,MAAM,MAAM,KAAK,YAAY,EAAE;AAAA,gBAAA;AAAA,gBAEtD,WAAW,GAAG,UAAU;AAAA,gBACxB,QAAQ,GAAG,UAAU;AAAA,gBACrB,YAAY;AAAA,cAAA;AAAA,cAEjB,UAAA;AAAA,gBAAA,oBAAC,KAAA,EAAI;AAAA,gBACJ,WAAW,IAAI,CAAC,OAAO,WACpB;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAA0C,SAAQ;AAAA,oBAAU,OAAM;AAAA,oBACvD,OAAO,EAAC,UAAU,IAAI,YAAY,GAAG,YAAY,UAAU,UAAU,WAAW,OAAO,YAAA;AAAA,oBAC9F,UAAA,QAAQ,qBAAqB,KAAK,IAAI;AAAA,kBAAA;AAAA,kBAFnB,SAAS,MAAM;AAAA,gBAAA,CAI1C;AAAA,gBACA,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,eACxB,qBAAC,aAAA,EAA0C,OAAO,EAAC,SAAS,cACxD,UAAA;AAAA,kBAAA;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBAAgB,SAAQ;AAAA,sBAAU,OAAM;AAAA,sBAC7B,OAAO,EAAC,UAAU,IAAI,YAAY,EAAC,IAAI,GAAG,YAAY,EAAE,MAAM,IAAI,GAAG,YAAY,EAAE,KAAA,GAAO,IAAI,KAAA;AAAA,sBACrG,2BAAiB,IAAI,UAAU,IAAI,uBAAuB,UAAU,IAAI;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAE5E,MAAM,IAAI,CAAC,MAAM,WAAW;AACzB,0BAAM,MAAM,KAAK,aAAa,CAAC;AAC/B,wBAAI,CAAC,KAAK;AACN,iDAAQ,KAAA,IAAS,WAAW,MAAM,IAAI,UAAU,EAAI;AAAA,oBACxD;AACA,0BAAM,QAAQ,QAAQ,IAAI,OAAO,UAAU;AAC3C,2BACI;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBAAuB,OAAK;AAAA,wBAAC,oBAAkB;AAAA,wBACvC,OAAO,GAAG,WAAW,IAAI,IAAI,CAAC,KAAK,cAAc,IAAI,KAAK,CAAC,GAAG,IAAI,SAAS,MAAM,IAAI,MAAM,KAAK,EAAE;AAAA,wBACvG,8BAAC,aAAA,EAAY,OAAO,CAAC,WAAW,EAAC,OAAO,aAAa,QAAQ,aAAa,cAAc,OAAO,SAAS,UAAU,OAAO,MAAM,KAAK,KAAC,CAAI;AAAA,sBAAA;AAAA,sBAF/H,IAAI;AAAA,oBAAA;AAAA,kBAK1B,CAAC;AAAA,gBAAA,EAAA,GAjBa,WAAW,UAAU,EAkBvC,CACH;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACL;AAAA,MAAA;AAAA;AAAA,IAIP,CAAC,WACE,qBAAC,iBAAc,WAAU,OAAM,SAAS,KAAK,OAAO,EAAC,YAAY,UAAU,gBAAgB,YAAY,IAAI,KAAI,eAAY,QACvH,UAAA;AAAA,MAAA,oBAAC,mBAAA,EAAkB,SAAQ,WAAU,OAAM,kBAAiB,OAAO,EAAC,IAAI,IAAA,GAAO,UAAA,EAAE,aAAa,EAAA,CAAE;AAAA,MAC/F,eAAe,IAAI,CAAC,UACjB,oBAAC,qBAA8B,OAAO,CAAC,WAAW,EAAC,OAAO,aAAa,QAAQ,aAAa,cAAc,OAAO,SAAS,UAAU,OAAO,MAAM,KAAK,EAAA,GAAC,GAA/H,KAAmI,CAC9J;AAAA,MACD,oBAAC,mBAAA,EAAkB,SAAQ,WAAU,OAAM,kBAAiB,OAAO,EAAC,IAAI,IAAA,GAAO,UAAA,EAAE,aAAa,EAAA,CAAE;AAAA,IAAA,EAAA,CACpG;AAAA,EAAA,GAER;AAER;"}
@@ -3,12 +3,16 @@ import { jsx } from "react/jsx-runtime";
3
3
  import Paper from "@mui/material/Paper";
4
4
  import Typography from "@mui/material/Typography";
5
5
  import { isGlassTheme, glassStylesOf } from "../../theme/glassSurface.js";
6
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
7
+ const THEME_NAME = "CalcitaChartTooltip";
8
+ const TooltipRoot = piecePart(THEME_NAME, "Root", Paper);
6
9
  const CHART_TOOLTIP_OPACITY = 0.92;
7
- function ChartTooltip({ active, payload, render }) {
10
+ function ChartTooltip(props) {
11
+ const { active, payload, render } = usePieceProps(props, THEME_NAME);
8
12
  if (!active || !payload?.length) {
9
13
  return null;
10
14
  }
11
- return /* @__PURE__ */ jsx(Paper, { elevation: 3, sx: [{ px: 1.5, py: 1, pointerEvents: "none" }, (theme) => isGlassTheme(theme) ? glassStylesOf(theme, { opacity: CHART_TOOLTIP_OPACITY }) : {}], children: /* @__PURE__ */ jsx(Typography, { variant: "body2", component: "div", children: render(payload[0].payload) }) });
15
+ return /* @__PURE__ */ jsx(TooltipRoot, { elevation: 3, ownSx: [{ px: 1.5, py: 1, pointerEvents: "none" }, (theme) => isGlassTheme(theme) ? glassStylesOf(theme, { opacity: CHART_TOOLTIP_OPACITY }) : {}], children: /* @__PURE__ */ jsx(Typography, { variant: "body2", component: "div", children: render(payload[0].payload) }) });
12
16
  }
13
17
  export {
14
18
  ChartTooltip as default
@@ -1 +1 @@
1
- {"version":3,"file":"ChartTooltip.js","sources":["../../../src/ui/metrics/ChartTooltip.jsx"],"sourcesContent":["// El tooltip de las gráficas de Recharts con el look de la app. Se exporta para las gráficas propias del proyecto con\n// recharts (una de pastel, una de área): <Tooltip content={<ChartTooltip render={(row) => …} />} />.\n//\n// El de Recharts trae su propio estilo (fondo blanco, borde gris); este usa el Paper del tema y habla igual que los\n// tooltips del resto de la app (y se voltea solo cuando llegue el modo oscuro). Con el vidrio del tema\n// (createToolkitTheme({glass: true})) es de vidrio: flota sobre la gráfica.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Paper from '@mui/material/Paper';\nimport Typography from '@mui/material/Typography';\n\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\n\n// el vidrio del cuadrito, casi opaco (el material «grueso»): es para leer una cifra encima de la gráfica; con el vidrio de\n// los controles (60 %) se veía la barra de atrás a través del texto (lo reportaron)\nconst CHART_TOOLTIP_OPACITY = 0.92;\n\n/**\n * @param {{active?: boolean, payload?: Array<{payload: any}>, render: (item: any) => import('react').ReactNode}} props\n * active y payload los pone recharts; render recibe el renglón de data del punto o la columna\n */\nexport default function ChartTooltip({active, payload, render}) {\n // guard clause: Recharts lo monta siempre; solo se pinta sobre una barra\n if (!active || !payload?.length) {\n return null;\n }\n return (\n <Paper elevation={3} sx={[{px: 1.5, py: 1, pointerEvents: 'none'}, (theme) => (isGlassTheme(theme) ? glassStylesOf(theme, {opacity: CHART_TOOLTIP_OPACITY}) : {})]}>\n {/* div: el globo puede llevar varios renglones (una serie por renglón) */}\n <Typography variant=\"body2\" component=\"div\">{render(payload[0].payload)}</Typography>\n </Paper>\n );\n}\n"],"names":[],"mappings":";;;;;AAeA,MAAM,wBAAwB;AAM9B,SAAwB,aAAa,EAAC,QAAQ,SAAS,UAAS;AAE5D,MAAI,CAAC,UAAU,CAAC,SAAS,QAAQ;AAC7B,WAAO;AAAA,EACX;AACA,6BACK,OAAA,EAAM,WAAW,GAAG,IAAI,CAAC,EAAC,IAAI,KAAK,IAAI,GAAG,eAAe,UAAS,CAAC,UAAW,aAAa,KAAK,IAAI,cAAc,OAAO,EAAC,SAAS,sBAAA,CAAsB,IAAI,EAAG,GAE7J,UAAA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,WAAU,OAAO,UAAA,OAAO,QAAQ,CAAC,EAAE,OAAO,GAAE,GAC5E;AAER;"}
1
+ {"version":3,"file":"ChartTooltip.js","sources":["../../../src/ui/metrics/ChartTooltip.jsx"],"sourcesContent":["// El tooltip de las gráficas de Recharts con el look de la app. Se exporta para las gráficas propias del proyecto con\n// recharts (una de pastel, una de área): <Tooltip content={<ChartTooltip render={(row) => …} />} />.\n//\n// El de Recharts trae su propio estilo (fondo blanco, borde gris); este usa el Paper del tema y habla igual que los\n// tooltips del resto de la app (y se voltea solo cuando llegue el modo oscuro). Con el vidrio del tema\n// (createToolkitTheme({glass: true})) es de vidrio: flota sobre la gráfica.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaChartTooltip con defaultProps y\n// styleOverrides de sus partes: root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Paper from '@mui/material/Paper';\nimport Typography from '@mui/material/Typography';\n\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaChartTooltip)\nconst THEME_NAME = 'CalcitaChartTooltip';\nconst TooltipRoot = piecePart(THEME_NAME, 'Root', Paper);\n\n// el vidrio del cuadrito, casi opaco (el material «grueso»): es para leer una cifra encima de la gráfica; con el vidrio de\n// los controles (60 %) se veía la barra de atrás a través del texto (lo reportaron)\nconst CHART_TOOLTIP_OPACITY = 0.92;\n\n/**\n * @param {{active?: boolean, payload?: Array<{payload: any}>, render: (item: any) => import('react').ReactNode}} props\n * active y payload los pone recharts; render recibe el renglón de data del punto o la columna\n */\nexport default function ChartTooltip(props) {\n // lo que el proyecto puso en su tema (components.CalcitaChartTooltip.defaultProps) y encima lo que llega aquí\n const {active, payload, render} = usePieceProps(props, THEME_NAME);\n // guard clause: Recharts lo monta siempre; solo se pinta sobre una barra\n if (!active || !payload?.length) {\n return null;\n }\n return (\n <TooltipRoot elevation={3} ownSx={[{px: 1.5, py: 1, pointerEvents: 'none'}, (theme) => (isGlassTheme(theme) ? glassStylesOf(theme, {opacity: CHART_TOOLTIP_OPACITY}) : {})]}>\n {/* div: el globo puede llevar varios renglones (una serie por renglón) */}\n <Typography variant=\"body2\" component=\"div\">{render(payload[0].payload)}</Typography>\n </TooltipRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;AAkBA,MAAM,aAAa;AACnB,MAAM,cAAc,UAAU,YAAY,QAAQ,KAAK;AAIvD,MAAM,wBAAwB;AAM9B,SAAwB,aAAa,OAAO;AAExC,QAAM,EAAC,QAAQ,SAAS,WAAU,cAAc,OAAO,UAAU;AAEjE,MAAI,CAAC,UAAU,CAAC,SAAS,QAAQ;AAC7B,WAAO;AAAA,EACX;AACA,6BACK,aAAA,EAAY,WAAW,GAAG,OAAO,CAAC,EAAC,IAAI,KAAK,IAAI,GAAG,eAAe,UAAS,CAAC,UAAW,aAAa,KAAK,IAAI,cAAc,OAAO,EAAC,SAAS,sBAAA,CAAsB,IAAI,EAAG,GAEtK,UAAA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,WAAU,OAAO,UAAA,OAAO,QAAQ,CAAC,EAAE,OAAO,GAAE,GAC5E;AAER;"}
@@ -9,24 +9,28 @@ import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
9
9
  import ChartTooltip from "./ChartTooltip.js";
10
10
  import TableToggle, { CHART_VIEW } from "./TableToggle.js";
11
11
  import { useChartColors, resolvedSeriesOf, highestValueOf, ChartTable, valueAxisWidthOf, ChartLegend, ReferenceCaption } from "./chartParts.js";
12
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
13
+ const THEME_NAME = "CalcitaColumnChart";
14
+ const ColumnChartPart = piecePart(THEME_NAME, "Chart", Box);
12
15
  const SINGLE_SERIES_KEY = "value";
13
- function ColumnChart({
14
- data,
15
- periodLabel,
16
- valueLabel,
17
- series,
18
- ariaLabel,
19
- emptyLabel,
20
- height = 220,
21
- tone = "primary",
22
- onSelect,
23
- formatValue: formatValueProp,
24
- referenceLine,
25
- renderTooltip,
26
- texts,
27
- defaultView = CHART_VIEW.chart,
28
- onViewChange
29
- }) {
16
+ function ColumnChart(props) {
17
+ const {
18
+ data,
19
+ periodLabel,
20
+ valueLabel,
21
+ series,
22
+ ariaLabel,
23
+ emptyLabel,
24
+ height = 220,
25
+ tone = "primary",
26
+ onSelect,
27
+ formatValue: formatValueProp,
28
+ referenceLine,
29
+ renderTooltip,
30
+ texts,
31
+ defaultView = CHART_VIEW.chart,
32
+ onViewChange
33
+ } = usePieceProps(props, THEME_NAME);
30
34
  const { t } = useToolkitTranslation("common", texts);
31
35
  const { formatNumber } = useFormatters();
32
36
  const formatValue = formatValueProp ?? formatNumber;
@@ -52,7 +56,7 @@ function ColumnChart({
52
56
  ] }));
53
57
  return /* @__PURE__ */ jsxs(Box, { children: [
54
58
  /* @__PURE__ */ jsx(TableToggle, { asTable, onToggle: toggleView, texts }),
55
- asTable ? /* @__PURE__ */ jsx(ChartTable, { data, series: drawnSeries, periodLabel, formatValue, height }) : /* @__PURE__ */ jsx(Box, { role: "img", "aria-label": ariaLabel, sx: { height, color: `${tone}.main` }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart, { data, margin: { top: 8, right: 8, bottom: 0, left: -8 }, barCategoryGap: 4, children: [
59
+ asTable ? /* @__PURE__ */ jsx(ChartTable, { data, series: drawnSeries, periodLabel, formatValue, height }) : /* @__PURE__ */ jsx(ColumnChartPart, { role: "img", "aria-label": ariaLabel, ownSx: { height, color: `${tone}.main` }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart, { data, margin: { top: 8, right: 8, bottom: 0, left: -8 }, barCategoryGap: 4, children: [
56
60
  /* @__PURE__ */ jsx(CartesianGrid, { vertical: false, stroke: colors.grid }),
57
61
  /* @__PURE__ */ jsx(
58
62
  XAxis,
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnChart.js","sources":["../../../src/ui/metrics/ColumnChart.jsx"],"sourcesContent":["// Columnas a lo largo del tiempo (p. ej. registros leídos por mes), dibujadas con Recharts: una serie (data con `value`) o\n// varias agrupadas por periodo (`series`, cada una con su llave en data: ventas y devoluciones por mes).\n//\n// Recharts y no SVG a mano: ejes, escalas, rótulos que no se encimen y el tooltip ya los resolvió la librería. Lo que se\n// decide aquí son las reglas de visualización:\n// - una serie → un color (el del tono vía currentColor) y SIN leyenda: el título ya dice qué es; varias → cada una su color\n// y leyenda abajo (chartParts.jsx, lo que comparte con LineChart);\n// - columnas de 28 px como máximo, punta redondeada, base cuadrada;\n// - rejilla horizontal de 1 px, sólida y recesiva; el texto de los ejes en tinta secundaria;\n// - tooltip por columna y VISTA DE TABLA;\n// - una línea de referencia opcional (p. ej. la meta), punteada y en tinta secundaria: se lee sin competir con las\n// columnas, y el eje crece lo necesario para que siempre se vea. Su rótulo va debajo de la gráfica y no sobre la\n// línea, donde se encimaba con la columna del último mes; así también lo lee quien ve la tabla.\n//\n// El valor se escribe con formatValue (por omisión, número con separador de miles): con él una serie puede ir en\n// porcentaje. El eje mide lo que mide su número más largo, para que «2,500,000» no salga cortado.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport {Bar, BarChart, CartesianGrid, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport ChartTooltip from '@/ui/metrics/ChartTooltip.jsx';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\nimport {\n ChartLegend, ChartTable, ReferenceCaption, highestValueOf, resolvedSeriesOf, useChartColors, valueAxisWidthOf,\n} from '@/ui/metrics/chartParts.jsx';\n\n// la llave del valor cuando la gráfica es de una sola serie\nconst SINGLE_SERIES_KEY = 'value';\n\n/**\n * @param {object} props\n * @param {Array<Record<string, any>>} props.data un renglón por periodo: {key, label, value, tooltip?} con una serie, o\n * {key, label, [llave de cada serie]: número} con varias\n * @param {string} props.periodLabel encabezado de la primera columna de la tabla («Mes»), ya traducido\n * @param {string} [props.valueLabel] cómo se llama lo que se cuenta, ya traducido (una serie)\n * @param {Array<{key: string, label: string, tone?: 'primary'|'secondary'|'success'|'warning'|'error'|'info'}>} [props.series]\n * varias series agrupadas: la llave de cada una en data, su nombre ya traducido y su color (por omisión, en orden)\n * @param {string} props.ariaLabel\n * @param {string} props.emptyLabel\n * @param {number} [props.height]\n * @param {'primary'|'success'|'warning'|'error'|'info'} [props.tone] el color de una sola serie\n * @param {(item: any, seriesKey: string) => void} [props.onSelect] recibe el renglón de data que se picó y la serie\n * @param {(value: number) => string} [props.formatValue] cómo se escribe un valor (en el eje, en la tabla y en el\n * tooltip)\n * @param {{value: number, label: string}} [props.referenceLine] línea de referencia con su rótulo ya traducido («Meta:\n * 10 %»)\n * @param {(row: any) => import('react').ReactNode} [props.renderTooltip] lo que dice el globo de un periodo; por omisión su\n * nombre y el valor de cada serie\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {charts: {viewAsTable, viewAsChart, legend}}\n */\nexport default function ColumnChart({\n data, periodLabel, valueLabel, series, ariaLabel, emptyLabel, height = 220, tone = 'primary', onSelect, formatValue: formatValueProp,\n referenceLine, renderTooltip, texts, defaultView = CHART_VIEW.chart, onViewChange,\n}) {\n const {t} = useToolkitTranslation('common', texts);\n const {formatNumber} = useFormatters();\n const formatValue = formatValueProp ?? formatNumber;\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n const isSingleSeries = !series?.length;\n const colors = useChartColors();\n const drawnSeries = resolvedSeriesOf(isSingleSeries ? [{key: SINGLE_SERIES_KEY, label: valueLabel, tone}] : series, colors.palette);\n\n // guard clause: sin datos se dice, no se pinta un eje vacío\n if (!data.length) {\n return <Typography variant=\"body2\" color=\"text.secondary\">{emptyLabel}</Typography>;\n }\n\n // el valor más alto que se dibuja (el de las columnas o el de la línea de referencia) decide el ancho del eje\n const highestValue = highestValueOf(data, drawnSeries, referenceLine);\n const tooltipOf = renderTooltip ?? ((row) => (isSingleSeries\n ? row.tooltip ?? `${row.label}: ${formatValue(row.value)}`\n : (\n <>\n <strong>{row.label}</strong>\n {drawnSeries.map((item) => <Box key={item.key}>{item.label}: {formatValue(row[item.key])}</Box>)}\n </>\n )));\n\n return (\n <Box>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n {asTable ? (\n <ChartTable data={data} series={drawnSeries} periodLabel={periodLabel} formatValue={formatValue} height={height} />\n ) : (\n <Box role=\"img\" aria-label={ariaLabel} sx={{height, color: `${tone}.main`}}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={data} margin={{top: 8, right: 8, bottom: 0, left: -8}} barCategoryGap={4}>\n <CartesianGrid vertical={false} stroke={colors.grid} />\n <XAxis dataKey=\"label\" tick={colors.axisText} tickLine={false} axisLine={{stroke: colors.grid}}\n interval=\"preserveStartEnd\" minTickGap={12} />\n <YAxis allowDecimals={false} tick={colors.axisText} tickLine={false} axisLine={false}\n width={valueAxisWidthOf(highestValue, formatValue)} tickFormatter={(value) => formatValue(value)} />\n <Tooltip cursor={{fill: colors.hover}} content={<ChartTooltip render={tooltipOf} />} />\n {referenceLine && (\n // extendDomain: si la referencia queda arriba de todas las columnas, el eje crece hasta ella\n <ReferenceLine y={referenceLine.value} ifOverflow=\"extendDomain\" stroke={colors.axis} strokeDasharray=\"4 4\" />\n )}\n {drawnSeries.map((item) => (\n // una serie: currentColor (el tono de la caja); varias: el color de cada una\n <Bar key={item.key} dataKey={item.key} fill={isSingleSeries ? 'currentColor' : item.color} maxBarSize={28}\n radius={[4, 4, 0, 0]} isAnimationActive={false} cursor={onSelect ? 'pointer' : 'default'}\n onClick={onSelect ? (entry) => onSelect(entry.payload, item.key) : undefined} />\n ))}\n </BarChart>\n </ResponsiveContainer>\n </Box>\n )}\n <ChartLegend series={drawnSeries} ariaLabel={t('charts.legend')} />\n <ReferenceCaption referenceLine={referenceLine} />\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ColumnChart.js","sources":["../../../src/ui/metrics/ColumnChart.jsx"],"sourcesContent":["// Columnas a lo largo del tiempo (p. ej. registros leídos por mes), dibujadas con Recharts: una serie (data con `value`) o\n// varias agrupadas por periodo (`series`, cada una con su llave en data: ventas y devoluciones por mes).\n//\n// Recharts y no SVG a mano: ejes, escalas, rótulos que no se encimen y el tooltip ya los resolvió la librería. Lo que se\n// decide aquí son las reglas de visualización:\n// - una serie → un color (el del tono vía currentColor) y SIN leyenda: el título ya dice qué es; varias → cada una su color\n// y leyenda abajo (chartParts.jsx, lo que comparte con LineChart);\n// - columnas de 28 px como máximo, punta redondeada, base cuadrada;\n// - rejilla horizontal de 1 px, sólida y recesiva; el texto de los ejes en tinta secundaria;\n// - tooltip por columna y VISTA DE TABLA;\n// - una línea de referencia opcional (p. ej. la meta), punteada y en tinta secundaria: se lee sin competir con las\n// columnas, y el eje crece lo necesario para que siempre se vea. Su rótulo va debajo de la gráfica y no sobre la\n// línea, donde se encimaba con la columna del último mes; así también lo lee quien ve la tabla.\n//\n// El valor se escribe con formatValue (por omisión, número con separador de miles): con él una serie puede ir en\n// porcentaje. El eje mide lo que mide su número más largo, para que «2,500,000» no salga cortado.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaColumnChart con defaultProps y\n// styleOverrides de sus partes: chart.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport {Bar, BarChart, CartesianGrid, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport ChartTooltip from '@/ui/metrics/ChartTooltip.jsx';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\nimport {\n ChartLegend, ChartTable, ReferenceCaption, highestValueOf, resolvedSeriesOf, useChartColors, valueAxisWidthOf,\n} from '@/ui/metrics/chartParts.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaColumnChart)\nconst THEME_NAME = 'CalcitaColumnChart';\nconst ColumnChartPart = piecePart(THEME_NAME, 'Chart', Box);\n\n// la llave del valor cuando la gráfica es de una sola serie\nconst SINGLE_SERIES_KEY = 'value';\n\n/**\n * @param {object} props\n * @param {Array<Record<string, any>>} props.data un renglón por periodo: {key, label, value, tooltip?} con una serie, o\n * {key, label, [llave de cada serie]: número} con varias\n * @param {string} props.periodLabel encabezado de la primera columna de la tabla («Mes»), ya traducido\n * @param {string} [props.valueLabel] cómo se llama lo que se cuenta, ya traducido (una serie)\n * @param {Array<{key: string, label: string, tone?: 'primary'|'secondary'|'success'|'warning'|'error'|'info'}>} [props.series]\n * varias series agrupadas: la llave de cada una en data, su nombre ya traducido y su color (por omisión, en orden)\n * @param {string} props.ariaLabel\n * @param {string} props.emptyLabel\n * @param {number} [props.height]\n * @param {'primary'|'success'|'warning'|'error'|'info'} [props.tone] el color de una sola serie\n * @param {(item: any, seriesKey: string) => void} [props.onSelect] recibe el renglón de data que se picó y la serie\n * @param {(value: number) => string} [props.formatValue] cómo se escribe un valor (en el eje, en la tabla y en el\n * tooltip)\n * @param {{value: number, label: string}} [props.referenceLine] línea de referencia con su rótulo ya traducido («Meta:\n * 10 %»)\n * @param {(row: any) => import('react').ReactNode} [props.renderTooltip] lo que dice el globo de un periodo; por omisión su\n * nombre y el valor de cada serie\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {charts: {viewAsTable, viewAsChart, legend}}\n */\nexport default function ColumnChart(props) {\n // lo que el proyecto puso en su tema (components.CalcitaColumnChart.defaultProps) y encima lo que llega aquí\n const {\n data, periodLabel, valueLabel, series, ariaLabel, emptyLabel, height = 220, tone = 'primary', onSelect, formatValue: formatValueProp,\n referenceLine, renderTooltip, texts, defaultView = CHART_VIEW.chart, onViewChange,\n} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('common', texts);\n const {formatNumber} = useFormatters();\n const formatValue = formatValueProp ?? formatNumber;\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n const isSingleSeries = !series?.length;\n const colors = useChartColors();\n const drawnSeries = resolvedSeriesOf(isSingleSeries ? [{key: SINGLE_SERIES_KEY, label: valueLabel, tone}] : series, colors.palette);\n\n // guard clause: sin datos se dice, no se pinta un eje vacío\n if (!data.length) {\n return <Typography variant=\"body2\" color=\"text.secondary\">{emptyLabel}</Typography>;\n }\n\n // el valor más alto que se dibuja (el de las columnas o el de la línea de referencia) decide el ancho del eje\n const highestValue = highestValueOf(data, drawnSeries, referenceLine);\n const tooltipOf = renderTooltip ?? ((row) => (isSingleSeries\n ? row.tooltip ?? `${row.label}: ${formatValue(row.value)}`\n : (\n <>\n <strong>{row.label}</strong>\n {drawnSeries.map((item) => <Box key={item.key}>{item.label}: {formatValue(row[item.key])}</Box>)}\n </>\n )));\n\n return (\n <Box>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n {asTable ? (\n <ChartTable data={data} series={drawnSeries} periodLabel={periodLabel} formatValue={formatValue} height={height} />\n ) : (\n <ColumnChartPart role=\"img\" aria-label={ariaLabel} ownSx={{height, color: `${tone}.main`}}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={data} margin={{top: 8, right: 8, bottom: 0, left: -8}} barCategoryGap={4}>\n <CartesianGrid vertical={false} stroke={colors.grid} />\n <XAxis dataKey=\"label\" tick={colors.axisText} tickLine={false} axisLine={{stroke: colors.grid}}\n interval=\"preserveStartEnd\" minTickGap={12} />\n <YAxis allowDecimals={false} tick={colors.axisText} tickLine={false} axisLine={false}\n width={valueAxisWidthOf(highestValue, formatValue)} tickFormatter={(value) => formatValue(value)} />\n <Tooltip cursor={{fill: colors.hover}} content={<ChartTooltip render={tooltipOf} />} />\n {referenceLine && (\n // extendDomain: si la referencia queda arriba de todas las columnas, el eje crece hasta ella\n <ReferenceLine y={referenceLine.value} ifOverflow=\"extendDomain\" stroke={colors.axis} strokeDasharray=\"4 4\" />\n )}\n {drawnSeries.map((item) => (\n // una serie: currentColor (el tono de la caja); varias: el color de cada una\n <Bar key={item.key} dataKey={item.key} fill={isSingleSeries ? 'currentColor' : item.color} maxBarSize={28}\n radius={[4, 4, 0, 0]} isAnimationActive={false} cursor={onSelect ? 'pointer' : 'default'}\n onClick={onSelect ? (entry) => onSelect(entry.payload, item.key) : undefined} />\n ))}\n </BarChart>\n </ResponsiveContainer>\n </ColumnChartPart>\n )}\n <ChartLegend series={drawnSeries} ariaLabel={t('charts.legend')} />\n <ReferenceCaption referenceLine={referenceLine} />\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -9,24 +9,28 @@ import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
9
9
  import ChartTooltip from "./ChartTooltip.js";
10
10
  import TableToggle, { CHART_VIEW } from "./TableToggle.js";
11
11
  import { useChartColors, resolvedSeriesOf, highestValueOf, ChartTable, valueAxisWidthOf, ChartLegend, ReferenceCaption } from "./chartParts.js";
12
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
13
+ const THEME_NAME = "CalcitaLineChart";
14
+ const LineChartPart = piecePart(THEME_NAME, "Chart", Box);
12
15
  const LINE_WIDTH_PIXELS = 2;
13
16
  const DOT_RADIUS_PIXELS = 3;
14
17
  const ACTIVE_DOT_RADIUS_PIXELS = 5;
15
- function LineChart({
16
- data,
17
- series,
18
- periodLabel,
19
- ariaLabel,
20
- emptyLabel,
21
- height = 220,
22
- formatValue: formatValueProp,
23
- referenceLine,
24
- onSelect,
25
- renderTooltip,
26
- texts,
27
- defaultView = CHART_VIEW.chart,
28
- onViewChange
29
- }) {
18
+ function LineChart(props) {
19
+ const {
20
+ data,
21
+ series,
22
+ periodLabel,
23
+ ariaLabel,
24
+ emptyLabel,
25
+ height = 220,
26
+ formatValue: formatValueProp,
27
+ referenceLine,
28
+ onSelect,
29
+ renderTooltip,
30
+ texts,
31
+ defaultView = CHART_VIEW.chart,
32
+ onViewChange
33
+ } = usePieceProps(props, THEME_NAME);
30
34
  const { t } = useToolkitTranslation("common", texts);
31
35
  const { formatNumber } = useFormatters();
32
36
  const formatValue = formatValueProp ?? formatNumber;
@@ -57,7 +61,7 @@ function LineChart({
57
61
  ] }));
58
62
  return /* @__PURE__ */ jsxs(Box, { children: [
59
63
  /* @__PURE__ */ jsx(TableToggle, { asTable, onToggle: toggleView, texts }),
60
- asTable ? /* @__PURE__ */ jsx(ChartTable, { data, series: drawnSeries, periodLabel, formatValue, height }) : /* @__PURE__ */ jsx(Box, { role: "img", "aria-label": ariaLabel, sx: { height }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
64
+ asTable ? /* @__PURE__ */ jsx(ChartTable, { data, series: drawnSeries, periodLabel, formatValue, height }) : /* @__PURE__ */ jsx(LineChartPart, { role: "img", "aria-label": ariaLabel, ownSx: { height }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
61
65
  LineChart$1,
62
66
  {
63
67
  data,
@@ -1 +1 @@
1
- {"version":3,"file":"LineChart.js","sources":["../../../src/ui/metrics/LineChart.jsx"],"sourcesContent":["// Líneas a lo largo del tiempo, de una serie o de varias que se comparan (ventas contra devoluciones, este año contra el\n// pasado), dibujadas con Recharts. Lo que comparte con ColumnChart (ejes, tabla, leyenda, línea de referencia) vive en\n// chartParts.jsx.\n//\n// Las reglas de la guía de Apple (HIG «Charts» y «Charting data»):\n// - líneas para ver la tendencia; columnas (ColumnChart) para comparar periodos sueltos;\n// - cada serie con su color Y su trazo (continuo, rayado, punteado), con su punto en cada periodo: el color no va solo;\n// - una serie sin leyenda (el título ya dice qué es); varias, con leyenda abajo; toda gráfica con su vista de tabla;\n// - el globo de un periodo dice el valor de cada serie.\n//\n// <LineChart data={[{key: '2026-4', label: 'abr', sales: 120, returns: 8}, …]} periodLabel=\"Mes\"\n// series={[{key: 'sales', label: 'Ventas'}, {key: 'returns', label: 'Devoluciones', tone: 'error'}]}\n// ariaLabel=\"Ventas y devoluciones por mes\" emptyLabel=\"Sin datos\" />\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport {CartesianGrid, Line, LineChart as RechartsLineChart, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport ChartTooltip from '@/ui/metrics/ChartTooltip.jsx';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\nimport {\n ChartLegend, ChartTable, ReferenceCaption, highestValueOf, resolvedSeriesOf, useChartColors, valueAxisWidthOf,\n} from '@/ui/metrics/chartParts.jsx';\n\n// el grueso de la línea y el tamaño de su punto (px): se ven en el teléfono sin tapar a la vecina\nconst LINE_WIDTH_PIXELS = 2;\nconst DOT_RADIUS_PIXELS = 3;\nconst ACTIVE_DOT_RADIUS_PIXELS = 5;\n\n/**\n * @param {object} props\n * @param {Array<Record<string, any>>} props.data un renglón por periodo: {key, label, [llave de cada serie]: número}\n * @param {Array<{key: string, label: string, tone?: 'primary'|'secondary'|'success'|'warning'|'error'|'info', dash?: string}>} props.series\n * la llave de cada serie en data, su nombre ya traducido, su color y su trazo (por omisión, en orden)\n * @param {string} props.periodLabel encabezado de la primera columna de la tabla («Mes»), ya traducido\n * @param {string} props.ariaLabel\n * @param {string} props.emptyLabel\n * @param {number} [props.height]\n * @param {(value: number) => string} [props.formatValue] cómo se escribe un valor (en el eje, en la tabla y en el globo)\n * @param {{value: number, label: string}} [props.referenceLine] línea de referencia (la meta) con su rótulo ya traducido\n * @param {(row: any) => void} [props.onSelect] recibe el renglón de data del periodo que se picó\n * @param {(row: any) => import('react').ReactNode} [props.renderTooltip] lo que dice el globo de un periodo; por omisión su\n * nombre y el valor de cada serie\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {charts: {viewAsTable, viewAsChart, legend}}\n */\nexport default function LineChart({\n data, series, periodLabel, ariaLabel, emptyLabel, height = 220, formatValue: formatValueProp, referenceLine, onSelect, renderTooltip, texts, defaultView = CHART_VIEW.chart, onViewChange,\n}) {\n const {t} = useToolkitTranslation('common', texts);\n const {formatNumber} = useFormatters();\n const formatValue = formatValueProp ?? formatNumber;\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n const colors = useChartColors();\n const drawnSeries = resolvedSeriesOf(series, colors.palette);\n\n // guard clause: sin datos se dice, no se pinta un eje vacío\n if (!data.length) {\n return <Typography variant=\"body2\" color=\"text.secondary\">{emptyLabel}</Typography>;\n }\n\n const highestValue = highestValueOf(data, drawnSeries, referenceLine);\n // el periodo que se picó: recharts da su posición en data (a veces como texto)\n const selectPeriodAt = (activeIndex) => {\n const row = data[Number(activeIndex)];\n if (row) {\n onSelect(row);\n }\n };\n const tooltipOf = renderTooltip ?? ((row) => (\n <>\n <strong>{row.label}</strong>\n {drawnSeries.map((item) => <Box key={item.key}>{item.label}: {formatValue(row[item.key])}</Box>)}\n </>\n ));\n\n return (\n <Box>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n {asTable ? (\n <ChartTable data={data} series={drawnSeries} periodLabel={periodLabel} formatValue={formatValue} height={height} />\n ) : (\n <Box role=\"img\" aria-label={ariaLabel} sx={{height}}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {/* OJO: recharts 3 avisa el clic con el índice del periodo (activeIndex), ya no con activePayload (el de\n la versión 2) */}\n <RechartsLineChart data={data} margin={{top: 8, right: 12, bottom: 0, left: -8}}\n onClick={onSelect ? (state) => selectPeriodAt(state?.activeIndex) : undefined}>\n <CartesianGrid vertical={false} stroke={colors.grid} />\n <XAxis dataKey=\"label\" tick={colors.axisText} tickLine={false} axisLine={{stroke: colors.grid}}\n interval=\"preserveStartEnd\" minTickGap={12} />\n <YAxis allowDecimals={false} tick={colors.axisText} tickLine={false} axisLine={false}\n width={valueAxisWidthOf(highestValue, formatValue)} tickFormatter={(value) => formatValue(value)} />\n <Tooltip cursor={{stroke: colors.grid}} content={<ChartTooltip render={tooltipOf} />} />\n {referenceLine && (\n <ReferenceLine y={referenceLine.value} ifOverflow=\"extendDomain\" stroke={colors.axis} strokeDasharray=\"4 4\" />\n )}\n {drawnSeries.map((item) => (\n <Line key={item.key} type=\"monotone\" dataKey={item.key} name={item.label} stroke={item.color}\n strokeWidth={LINE_WIDTH_PIXELS} strokeDasharray={item.dash} isAnimationActive={false}\n dot={{r: DOT_RADIUS_PIXELS, fill: item.color, strokeWidth: 0}}\n activeDot={{r: ACTIVE_DOT_RADIUS_PIXELS, cursor: onSelect ? 'pointer' : 'default'}} />\n ))}\n </RechartsLineChart>\n </ResponsiveContainer>\n </Box>\n )}\n <ChartLegend series={drawnSeries} showsDash ariaLabel={t('charts.legend')} />\n <ReferenceCaption referenceLine={referenceLine} />\n </Box>\n );\n}\n"],"names":["RechartsLineChart"],"mappings":";;;;;;;;;;;AA6BA,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAC1B,MAAM,2BAA2B;AAoBjC,SAAwB,UAAU;AAAA,EAC9B;AAAA,EAAM;AAAA,EAAQ;AAAA,EAAa;AAAA,EAAW;AAAA,EAAY,SAAS;AAAA,EAAK,aAAa;AAAA,EAAiB;AAAA,EAAe;AAAA,EAAU;AAAA,EAAe;AAAA,EAAO,cAAc,WAAW;AAAA,EAAO;AACjL,GAAG;AACC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,EAAC,aAAA,IAAgB,cAAA;AACvB,QAAM,cAAc,mBAAmB;AACvC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,gBAAgB,WAAW,KAAK;AACvE,QAAM,aAAa,MAAM;AACrB,eAAW,CAAC,OAAO;AACnB,mBAAe,UAAU,WAAW,QAAQ,WAAW,KAAK;AAAA,EAChE;AACA,QAAM,SAAS,eAAA;AACf,QAAM,cAAc,iBAAiB,QAAQ,OAAO,OAAO;AAG3D,MAAI,CAAC,KAAK,QAAQ;AACd,+BAAQ,YAAA,EAAW,SAAQ,SAAQ,OAAM,kBAAkB,UAAA,YAAW;AAAA,EAC1E;AAEA,QAAM,eAAe,eAAe,MAAM,aAAa,aAAa;AAEpE,QAAM,iBAAiB,CAAC,gBAAgB;AACpC,UAAM,MAAM,KAAK,OAAO,WAAW,CAAC;AACpC,QAAI,KAAK;AACL,eAAS,GAAG;AAAA,IAChB;AAAA,EACJ;AACA,QAAM,YAAY,kBAAkB,CAAC,QACjC,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA,oBAAC,UAAA,EAAQ,cAAI,MAAA,CAAM;AAAA,IAClB,YAAY,IAAI,CAAC,8BAAU,KAAA,EAAoB,UAAA;AAAA,MAAA,KAAK;AAAA,MAAM;AAAA,MAAG,YAAY,IAAI,KAAK,GAAG,CAAC;AAAA,IAAA,EAAA,GAAlD,KAAK,GAA+C,CAAM;AAAA,EAAA,EAAA,CACnG;AAGJ,8BACK,KAAA,EACG,UAAA;AAAA,IAAA,oBAAC,aAAA,EAAY,SAAkB,UAAU,YAAY,OAAc;AAAA,IAClE,UACG,oBAAC,YAAA,EAAW,MAAY,QAAQ,aAAa,aAA0B,aAA0B,OAAA,CAAgB,IAEjH,oBAAC,KAAA,EAAI,MAAK,OAAM,cAAY,WAAW,IAAI,EAAC,OAAA,GACxC,UAAA,oBAAC,qBAAA,EAAoB,OAAM,QAAO,QAAO,QAGrC,UAAA;AAAA,MAACA;AAAAA,MAAA;AAAA,QAAkB;AAAA,QAAY,QAAQ,EAAC,KAAK,GAAG,OAAO,IAAI,QAAQ,GAAG,MAAM,GAAA;AAAA,QACzD,SAAS,WAAW,CAAC,UAAU,eAAe,OAAO,WAAW,IAAI;AAAA,QACnF,UAAA;AAAA,UAAA,oBAAC,eAAA,EAAc,UAAU,OAAO,QAAQ,OAAO,MAAM;AAAA,UACrD;AAAA,YAAC;AAAA,YAAA;AAAA,cAAM,SAAQ;AAAA,cAAQ,MAAM,OAAO;AAAA,cAAU,UAAU;AAAA,cAAO,UAAU,EAAC,QAAQ,OAAO,KAAA;AAAA,cAClF,UAAS;AAAA,cAAmB,YAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAC/C;AAAA,YAAC;AAAA,YAAA;AAAA,cAAM,eAAe;AAAA,cAAO,MAAM,OAAO;AAAA,cAAU,UAAU;AAAA,cAAO,UAAU;AAAA,cACxE,OAAO,iBAAiB,cAAc,WAAW;AAAA,cAAG,eAAe,CAAC,UAAU,YAAY,KAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UACtG,oBAAC,SAAA,EAAQ,QAAQ,EAAC,QAAQ,OAAO,KAAA,GAAO,SAAS,oBAAC,cAAA,EAAa,QAAQ,WAAW,EAAA,CAAI;AAAA,UACrF,iBACG,oBAAC,eAAA,EAAc,GAAG,cAAc,OAAO,YAAW,gBAAe,QAAQ,OAAO,MAAM,iBAAgB,MAAA,CAAM;AAAA,UAE/G,YAAY,IAAI,CAAC,SACd;AAAA,YAAC;AAAA,YAAA;AAAA,cAAoB,MAAK;AAAA,cAAW,SAAS,KAAK;AAAA,cAAK,MAAM,KAAK;AAAA,cAAO,QAAQ,KAAK;AAAA,cACjF,aAAa;AAAA,cAAmB,iBAAiB,KAAK;AAAA,cAAM,mBAAmB;AAAA,cAC/E,KAAK,EAAC,GAAG,mBAAmB,MAAM,KAAK,OAAO,aAAa,EAAA;AAAA,cAC3D,WAAW,EAAC,GAAG,0BAA0B,QAAQ,WAAW,YAAY,UAAA;AAAA,YAAS;AAAA,YAH5E,KAAK;AAAA,UAAA,CAInB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAET,EAAA,CACJ;AAAA,IAEJ,oBAAC,eAAY,QAAQ,aAAa,WAAS,MAAC,WAAW,EAAE,eAAe,GAAG;AAAA,IAC3E,oBAAC,oBAAiB,cAAA,CAA8B;AAAA,EAAA,GACpD;AAER;"}
1
+ {"version":3,"file":"LineChart.js","sources":["../../../src/ui/metrics/LineChart.jsx"],"sourcesContent":["// Líneas a lo largo del tiempo, de una serie o de varias que se comparan (ventas contra devoluciones, este año contra el\n// pasado), dibujadas con Recharts. Lo que comparte con ColumnChart (ejes, tabla, leyenda, línea de referencia) vive en\n// chartParts.jsx.\n//\n// Las reglas de la guía de Apple (HIG «Charts» y «Charting data»):\n// - líneas para ver la tendencia; columnas (ColumnChart) para comparar periodos sueltos;\n// - cada serie con su color Y su trazo (continuo, rayado, punteado), con su punto en cada periodo: el color no va solo;\n// - una serie sin leyenda (el título ya dice qué es); varias, con leyenda abajo; toda gráfica con su vista de tabla;\n// - el globo de un periodo dice el valor de cada serie.\n//\n// <LineChart data={[{key: '2026-4', label: 'abr', sales: 120, returns: 8}, …]} periodLabel=\"Mes\"\n// series={[{key: 'sales', label: 'Ventas'}, {key: 'returns', label: 'Devoluciones', tone: 'error'}]}\n// ariaLabel=\"Ventas y devoluciones por mes\" emptyLabel=\"Sin datos\" />\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaLineChart con defaultProps y\n// styleOverrides de sus partes: chart.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport {CartesianGrid, Line, LineChart as RechartsLineChart, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis} from 'recharts';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport ChartTooltip from '@/ui/metrics/ChartTooltip.jsx';\nimport TableToggle, {CHART_VIEW} from '@/ui/metrics/TableToggle.jsx';\nimport {\n ChartLegend, ChartTable, ReferenceCaption, highestValueOf, resolvedSeriesOf, useChartColors, valueAxisWidthOf,\n} from '@/ui/metrics/chartParts.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaLineChart)\nconst THEME_NAME = 'CalcitaLineChart';\nconst LineChartPart = piecePart(THEME_NAME, 'Chart', Box);\n\n// el grueso de la línea y el tamaño de su punto (px): se ven en el teléfono sin tapar a la vecina\nconst LINE_WIDTH_PIXELS = 2;\nconst DOT_RADIUS_PIXELS = 3;\nconst ACTIVE_DOT_RADIUS_PIXELS = 5;\n\n/**\n * @param {object} props\n * @param {Array<Record<string, any>>} props.data un renglón por periodo: {key, label, [llave de cada serie]: número}\n * @param {Array<{key: string, label: string, tone?: 'primary'|'secondary'|'success'|'warning'|'error'|'info', dash?: string}>} props.series\n * la llave de cada serie en data, su nombre ya traducido, su color y su trazo (por omisión, en orden)\n * @param {string} props.periodLabel encabezado de la primera columna de la tabla («Mes»), ya traducido\n * @param {string} props.ariaLabel\n * @param {string} props.emptyLabel\n * @param {number} [props.height]\n * @param {(value: number) => string} [props.formatValue] cómo se escribe un valor (en el eje, en la tabla y en el globo)\n * @param {{value: number, label: string}} [props.referenceLine] línea de referencia (la meta) con su rótulo ya traducido\n * @param {(row: any) => void} [props.onSelect] recibe el renglón de data del periodo que se picó\n * @param {(row: any) => import('react').ReactNode} [props.renderTooltip] lo que dice el globo de un periodo; por omisión su\n * nombre y el valor de cada serie\n * @param {'chart'|'table'} [props.defaultView] cómo se ve al abrir (CHART_VIEW); por omisión dibujada\n * @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {charts: {viewAsTable, viewAsChart, legend}}\n */\nexport default function LineChart(props) {\n // lo que el proyecto puso en su tema (components.CalcitaLineChart.defaultProps) y encima lo que llega aquí\n const {\n data, series, periodLabel, ariaLabel, emptyLabel, height = 220, formatValue: formatValueProp, referenceLine, onSelect, renderTooltip, texts, defaultView = CHART_VIEW.chart, onViewChange,\n} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('common', texts);\n const {formatNumber} = useFormatters();\n const formatValue = formatValueProp ?? formatNumber;\n const [asTable, setAsTable] = useState(defaultView === CHART_VIEW.table);\n const toggleView = () => {\n setAsTable(!asTable);\n onViewChange?.(asTable ? CHART_VIEW.chart : CHART_VIEW.table);\n };\n const colors = useChartColors();\n const drawnSeries = resolvedSeriesOf(series, colors.palette);\n\n // guard clause: sin datos se dice, no se pinta un eje vacío\n if (!data.length) {\n return <Typography variant=\"body2\" color=\"text.secondary\">{emptyLabel}</Typography>;\n }\n\n const highestValue = highestValueOf(data, drawnSeries, referenceLine);\n // el periodo que se picó: recharts da su posición en data (a veces como texto)\n const selectPeriodAt = (activeIndex) => {\n const row = data[Number(activeIndex)];\n if (row) {\n onSelect(row);\n }\n };\n const tooltipOf = renderTooltip ?? ((row) => (\n <>\n <strong>{row.label}</strong>\n {drawnSeries.map((item) => <Box key={item.key}>{item.label}: {formatValue(row[item.key])}</Box>)}\n </>\n ));\n\n return (\n <Box>\n <TableToggle asTable={asTable} onToggle={toggleView} texts={texts} />\n {asTable ? (\n <ChartTable data={data} series={drawnSeries} periodLabel={periodLabel} formatValue={formatValue} height={height} />\n ) : (\n <LineChartPart role=\"img\" aria-label={ariaLabel} ownSx={{height}}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {/* OJO: recharts 3 avisa el clic con el índice del periodo (activeIndex), ya no con activePayload (el de\n la versión 2) */}\n <RechartsLineChart data={data} margin={{top: 8, right: 12, bottom: 0, left: -8}}\n onClick={onSelect ? (state) => selectPeriodAt(state?.activeIndex) : undefined}>\n <CartesianGrid vertical={false} stroke={colors.grid} />\n <XAxis dataKey=\"label\" tick={colors.axisText} tickLine={false} axisLine={{stroke: colors.grid}}\n interval=\"preserveStartEnd\" minTickGap={12} />\n <YAxis allowDecimals={false} tick={colors.axisText} tickLine={false} axisLine={false}\n width={valueAxisWidthOf(highestValue, formatValue)} tickFormatter={(value) => formatValue(value)} />\n <Tooltip cursor={{stroke: colors.grid}} content={<ChartTooltip render={tooltipOf} />} />\n {referenceLine && (\n <ReferenceLine y={referenceLine.value} ifOverflow=\"extendDomain\" stroke={colors.axis} strokeDasharray=\"4 4\" />\n )}\n {drawnSeries.map((item) => (\n <Line key={item.key} type=\"monotone\" dataKey={item.key} name={item.label} stroke={item.color}\n strokeWidth={LINE_WIDTH_PIXELS} strokeDasharray={item.dash} isAnimationActive={false}\n dot={{r: DOT_RADIUS_PIXELS, fill: item.color, strokeWidth: 0}}\n activeDot={{r: ACTIVE_DOT_RADIUS_PIXELS, cursor: onSelect ? 'pointer' : 'default'}} />\n ))}\n </RechartsLineChart>\n </ResponsiveContainer>\n </LineChartPart>\n )}\n <ChartLegend series={drawnSeries} showsDash ariaLabel={t('charts.legend')} />\n <ReferenceCaption referenceLine={referenceLine} />\n </Box>\n );\n}\n"],"names":["RechartsLineChart"],"mappings":"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"}