@ifto/mantine-kit 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +471 -2
  3. package/dist/component/atom/AppMain/App.module.js +7 -0
  4. package/dist/component/atom/AppMain/App.module.js.map +1 -0
  5. package/dist/component/atom/AppMain/AppMain.d.ts +7 -0
  6. package/dist/component/atom/AppMain/AppMain.js +14 -0
  7. package/dist/component/atom/AppMain/AppMain.js.map +1 -0
  8. package/dist/component/atom/CancelEditButton/CancelEditButton.d.ts +6 -0
  9. package/dist/component/atom/CancelEditButton/CancelEditButton.js +24 -0
  10. package/dist/component/atom/CancelEditButton/CancelEditButton.js.map +1 -0
  11. package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.d.ts +13 -0
  12. package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.js +30 -0
  13. package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.js.map +1 -0
  14. package/dist/component/atom/DateField/DateField.d.ts +7 -0
  15. package/dist/component/atom/DateField/DateField.js +21 -0
  16. package/dist/component/atom/DateField/DateField.js.map +1 -0
  17. package/dist/component/atom/EditValueButton/EditValueButton.d.ts +6 -0
  18. package/dist/component/atom/EditValueButton/EditValueButton.js +24 -0
  19. package/dist/component/atom/EditValueButton/EditValueButton.js.map +1 -0
  20. package/dist/component/atom/ErrorAlert/ErrorAlert.d.ts +8 -0
  21. package/dist/component/atom/ErrorAlert/ErrorAlert.js +21 -0
  22. package/dist/component/atom/ErrorAlert/ErrorAlert.js.map +1 -0
  23. package/dist/component/atom/Surface/Surface.d.ts +20 -0
  24. package/dist/component/atom/Surface/Surface.js +15 -0
  25. package/dist/component/atom/Surface/Surface.js.map +1 -0
  26. package/dist/component/molecule/Breadcrumb/Breadcrumb.d.ts +12 -0
  27. package/dist/component/molecule/Breadcrumb/Breadcrumb.js +38 -0
  28. package/dist/component/molecule/Breadcrumb/Breadcrumb.js.map +1 -0
  29. package/dist/component/molecule/ExportMenuButton/ExportMenuButton.d.ts +25 -0
  30. package/dist/component/molecule/ExportMenuButton/ExportMenuButton.js +49 -0
  31. package/dist/component/molecule/ExportMenuButton/ExportMenuButton.js.map +1 -0
  32. package/dist/component/molecule/PaperCard/PaperCard.d.ts +7 -0
  33. package/dist/component/molecule/PaperCard/PaperCard.js +17 -0
  34. package/dist/component/molecule/PaperCard/PaperCard.js.map +1 -0
  35. package/dist/component/molecule/PrintSection/PrintSection.d.ts +14 -0
  36. package/dist/component/molecule/PrintSection/PrintSection.js +29 -0
  37. package/dist/component/molecule/PrintSection/PrintSection.js.map +1 -0
  38. package/dist/component/molecule/SelectField/SelectField.d.ts +32 -0
  39. package/dist/component/molecule/SelectField/SelectField.js +38 -0
  40. package/dist/component/molecule/SelectField/SelectField.js.map +1 -0
  41. package/dist/component/molecule/StatsCard/Stats.module.js +15 -0
  42. package/dist/component/molecule/StatsCard/Stats.module.js.map +1 -0
  43. package/dist/component/molecule/StatsCard/StatsCard.d.ts +18 -0
  44. package/dist/component/molecule/StatsCard/StatsCard.js +60 -0
  45. package/dist/component/molecule/StatsCard/StatsCard.js.map +1 -0
  46. package/dist/component/organism/DataForm/DataForm.d.ts +26 -0
  47. package/dist/component/organism/DataForm/DataForm.js +83 -0
  48. package/dist/component/organism/DataForm/DataForm.js.map +1 -0
  49. package/dist/component/organism/DataTabList/DataTabList.d.ts +24 -0
  50. package/dist/component/organism/DataTabList/DataTabList.js +37 -0
  51. package/dist/component/organism/DataTabList/DataTabList.js.map +1 -0
  52. package/dist/component/organism/DataTabList/DataTabList.module.js +13 -0
  53. package/dist/component/organism/DataTabList/DataTabList.module.js.map +1 -0
  54. package/dist/component/organism/EChart/EChart.d.ts +47 -0
  55. package/dist/component/organism/EChart/EChart.js +37 -0
  56. package/dist/component/organism/EChart/EChart.js.map +1 -0
  57. package/dist/component/organism/EChart/buildEChartOption.d.ts +40 -0
  58. package/dist/component/organism/EChart/buildEChartOption.js +57 -0
  59. package/dist/component/organism/EChart/buildEChartOption.js.map +1 -0
  60. package/dist/component/organism/EChart/chart/BarChart.d.ts +22 -0
  61. package/dist/component/organism/EChart/chart/BarChart.js +34 -0
  62. package/dist/component/organism/EChart/chart/BarChart.js.map +1 -0
  63. package/dist/component/organism/EChart/chart/CartesianChart.d.ts +48 -0
  64. package/dist/component/organism/EChart/chart/CartesianChart.js +63 -0
  65. package/dist/component/organism/EChart/chart/CartesianChart.js.map +1 -0
  66. package/dist/component/organism/EChart/chart/ChartHeader.d.ts +36 -0
  67. package/dist/component/organism/EChart/chart/ChartHeader.js +105 -0
  68. package/dist/component/organism/EChart/chart/ChartHeader.js.map +1 -0
  69. package/dist/component/organism/EChart/chart/ChartSeries.d.ts +50 -0
  70. package/dist/component/organism/EChart/chart/ChartSeries.js +23 -0
  71. package/dist/component/organism/EChart/chart/ChartSeries.js.map +1 -0
  72. package/dist/component/organism/EChart/chart/ChartTexts.d.ts +12 -0
  73. package/dist/component/organism/EChart/chart/ChartTexts.js +21 -0
  74. package/dist/component/organism/EChart/chart/ChartTexts.js.map +1 -0
  75. package/dist/component/organism/EChart/chart/ChartType.d.ts +50 -0
  76. package/dist/component/organism/EChart/chart/ChartType.js +1 -0
  77. package/dist/component/organism/EChart/chart/ChartTypeId.d.ts +2 -0
  78. package/dist/component/organism/EChart/chart/ChartTypeId.js +1 -0
  79. package/dist/component/organism/EChart/chart/ChartTypes.d.ts +15 -0
  80. package/dist/component/organism/EChart/chart/ChartTypes.js +24 -0
  81. package/dist/component/organism/EChart/chart/ChartTypes.js.map +1 -0
  82. package/dist/component/organism/EChart/chart/DonutChart.d.ts +32 -0
  83. package/dist/component/organism/EChart/chart/DonutChart.js +111 -0
  84. package/dist/component/organism/EChart/chart/DonutChart.js.map +1 -0
  85. package/dist/component/organism/EChart/chart/LineChart.d.ts +11 -0
  86. package/dist/component/organism/EChart/chart/LineChart.js +20 -0
  87. package/dist/component/organism/EChart/chart/LineChart.js.map +1 -0
  88. package/dist/component/organism/EChart/chart/StackedBarChart.d.ts +15 -0
  89. package/dist/component/organism/EChart/chart/StackedBarChart.js +30 -0
  90. package/dist/component/organism/EChart/chart/StackedBarChart.js.map +1 -0
  91. package/dist/component/organism/EChart/chart/UnitPanels.d.ts +63 -0
  92. package/dist/component/organism/EChart/chart/UnitPanels.js +127 -0
  93. package/dist/component/organism/EChart/chart/UnitPanels.js.map +1 -0
  94. package/dist/component/organism/EChart/echartDefaults.d.ts +32 -0
  95. package/dist/component/organism/EChart/echartDefaults.js +47 -0
  96. package/dist/component/organism/EChart/echartDefaults.js.map +1 -0
  97. package/dist/component/organism/EChart/useEChart.d.ts +35 -0
  98. package/dist/component/organism/EChart/useEChart.js +112 -0
  99. package/dist/component/organism/EChart/useEChart.js.map +1 -0
  100. package/dist/component/organism/Navbar/NavItem.d.ts +16 -0
  101. package/dist/component/organism/Navbar/NavItem.js +1 -0
  102. package/dist/component/organism/Navbar/Navbar.d.ts +20 -0
  103. package/dist/component/organism/Navbar/Navbar.js +64 -0
  104. package/dist/component/organism/Navbar/Navbar.js.map +1 -0
  105. package/dist/component/organism/Navbar/Navbar.module.js +19 -0
  106. package/dist/component/organism/Navbar/Navbar.module.js.map +1 -0
  107. package/dist/component/organism/PageHeader/PageHeader.d.ts +14 -0
  108. package/dist/component/organism/PageHeader/PageHeader.js +55 -0
  109. package/dist/component/organism/PageHeader/PageHeader.js.map +1 -0
  110. package/dist/component/organism/StatsGrid/StatsGrid.d.ts +12 -0
  111. package/dist/component/organism/StatsGrid/StatsGrid.js +46 -0
  112. package/dist/component/organism/StatsGrid/StatsGrid.js.map +1 -0
  113. package/dist/component/organism/StatsGrid/StatsGrid.module.js +17 -0
  114. package/dist/component/organism/StatsGrid/StatsGrid.module.js.map +1 -0
  115. package/dist/component/organism/Table/RowActions.d.ts +23 -0
  116. package/dist/component/organism/Table/RowActions.js +121 -0
  117. package/dist/component/organism/Table/RowActions.js.map +1 -0
  118. package/dist/component/organism/Table/Table.d.ts +51 -0
  119. package/dist/component/organism/Table/Table.js +108 -0
  120. package/dist/component/organism/Table/Table.js.map +1 -0
  121. package/dist/component/organism/ViewTable/ColumnComparator.d.ts +11 -0
  122. package/dist/component/organism/ViewTable/ColumnComparator.js +25 -0
  123. package/dist/component/organism/ViewTable/ColumnComparator.js.map +1 -0
  124. package/dist/component/organism/ViewTable/ViewTable.d.ts +53 -0
  125. package/dist/component/organism/ViewTable/ViewTable.js +123 -0
  126. package/dist/component/organism/ViewTable/ViewTable.js.map +1 -0
  127. package/dist/component/template/CreateFormPage/CreateFormPage.d.ts +19 -0
  128. package/dist/component/template/CreateFormPage/CreateFormPage.js +41 -0
  129. package/dist/component/template/CreateFormPage/CreateFormPage.js.map +1 -0
  130. package/dist/component/template/EditFormPage/EditFormPage.d.ts +19 -0
  131. package/dist/component/template/EditFormPage/EditFormPage.js +42 -0
  132. package/dist/component/template/EditFormPage/EditFormPage.js.map +1 -0
  133. package/dist/component/template/FormPage/FormPage.d.ts +25 -0
  134. package/dist/component/template/FormPage/FormPage.js +130 -0
  135. package/dist/component/template/FormPage/FormPage.js.map +1 -0
  136. package/dist/component/template/FormPage/FormType.d.ts +6 -0
  137. package/dist/component/template/FormPage/FormType.js +12 -0
  138. package/dist/component/template/FormPage/FormType.js.map +1 -0
  139. package/dist/component/template/Layout/Layout.d.ts +21 -0
  140. package/dist/component/template/Layout/Layout.js +121 -0
  141. package/dist/component/template/Layout/Layout.js.map +1 -0
  142. package/dist/component/template/Layout/Layout.module.js +19 -0
  143. package/dist/component/template/Layout/Layout.module.js.map +1 -0
  144. package/dist/component/template/ListPage/ListPage.d.ts +32 -0
  145. package/dist/component/template/ListPage/ListPage.js +47 -0
  146. package/dist/component/template/ListPage/ListPage.js.map +1 -0
  147. package/dist/component/template/PrintPage/PrintPage.d.ts +25 -0
  148. package/dist/component/template/PrintPage/PrintPage.js +115 -0
  149. package/dist/component/template/PrintPage/PrintPage.js.map +1 -0
  150. package/dist/component/template/ViewPage/ViewPage.d.ts +11 -0
  151. package/dist/component/template/ViewPage/ViewPage.js +49 -0
  152. package/dist/component/template/ViewPage/ViewPage.js.map +1 -0
  153. package/dist/data/ListDataSource.d.ts +12 -0
  154. package/dist/data/ListDataSource.js +1 -0
  155. package/dist/data/SaveDataSource.d.ts +16 -0
  156. package/dist/data/SaveDataSource.js +1 -0
  157. package/dist/export/ExportCellText.d.ts +18 -0
  158. package/dist/export/ExportCellText.js +60 -0
  159. package/dist/export/ExportCellText.js.map +1 -0
  160. package/dist/export/ExportDocument.d.ts +127 -0
  161. package/dist/export/ExportDocument.js +59 -0
  162. package/dist/export/ExportDocument.js.map +1 -0
  163. package/dist/export/ExportDownload.d.ts +9 -0
  164. package/dist/export/ExportDownload.js +19 -0
  165. package/dist/export/ExportDownload.js.map +1 -0
  166. package/dist/export/ExportFileName.d.ts +11 -0
  167. package/dist/export/ExportFileName.js +24 -0
  168. package/dist/export/ExportFileName.js.map +1 -0
  169. package/dist/export/ExportFormat.d.ts +30 -0
  170. package/dist/export/ExportFormat.js +1 -0
  171. package/dist/export/ExportFormats.d.ts +12 -0
  172. package/dist/export/ExportFormats.js +16 -0
  173. package/dist/export/ExportFormats.js.map +1 -0
  174. package/dist/export/ExportTexts.d.ts +14 -0
  175. package/dist/export/ExportTexts.js +23 -0
  176. package/dist/export/ExportTexts.js.map +1 -0
  177. package/dist/export/csv/CsvFormat.d.ts +41 -0
  178. package/dist/export/csv/CsvFormat.js +91 -0
  179. package/dist/export/csv/CsvFormat.js.map +1 -0
  180. package/dist/export/xlsx/XlsxFormat.d.ts +35 -0
  181. package/dist/export/xlsx/XlsxFormat.js +66 -0
  182. package/dist/export/xlsx/XlsxFormat.js.map +1 -0
  183. package/dist/export/xlsx/XlsxNumberFormat.d.ts +8 -0
  184. package/dist/export/xlsx/XlsxNumberFormat.js +15 -0
  185. package/dist/export/xlsx/XlsxNumberFormat.js.map +1 -0
  186. package/dist/export/xlsx/XlsxSheetName.d.ts +12 -0
  187. package/dist/export/xlsx/XlsxSheetName.js +62 -0
  188. package/dist/export/xlsx/XlsxSheetName.js.map +1 -0
  189. package/dist/export/xlsx/XlsxSheetWriter.d.ts +67 -0
  190. package/dist/export/xlsx/XlsxSheetWriter.js +215 -0
  191. package/dist/export/xlsx/XlsxSheetWriter.js.map +1 -0
  192. package/dist/export/xlsx/XlsxStyle.d.ts +51 -0
  193. package/dist/export/xlsx/XlsxStyle.js +87 -0
  194. package/dist/export/xlsx/XlsxStyle.js.map +1 -0
  195. package/dist/hook/useIsMobile.d.ts +5 -0
  196. package/dist/hook/useIsMobile.js +16 -0
  197. package/dist/hook/useIsMobile.js.map +1 -0
  198. package/dist/hook/useKeyedService.d.ts +22 -0
  199. package/dist/hook/useKeyedService.js +38 -0
  200. package/dist/hook/useKeyedService.js.map +1 -0
  201. package/dist/hook/useLightColorSchemeOnPrint.d.ts +9 -0
  202. package/dist/hook/useLightColorSchemeOnPrint.js +36 -0
  203. package/dist/hook/useLightColorSchemeOnPrint.js.map +1 -0
  204. package/dist/hook/useService.d.ts +12 -0
  205. package/dist/hook/useService.js +29 -0
  206. package/dist/hook/useService.js.map +1 -0
  207. package/dist/http/ApiError.d.ts +13 -0
  208. package/dist/http/ApiError.js +22 -0
  209. package/dist/http/ApiError.js.map +1 -0
  210. package/dist/http/AxiosHttpClient.d.ts +21 -0
  211. package/dist/http/AxiosHttpClient.js +67 -0
  212. package/dist/http/AxiosHttpClient.js.map +1 -0
  213. package/dist/http/AxiosHttpClientConfig.d.ts +37 -0
  214. package/dist/http/AxiosHttpClientConfig.js +19 -0
  215. package/dist/http/AxiosHttpClientConfig.js.map +1 -0
  216. package/dist/i18n/KitLocale.d.ts +4 -0
  217. package/dist/i18n/KitLocale.js +7 -0
  218. package/dist/i18n/KitLocale.js.map +1 -0
  219. package/dist/i18n/KitMessages.d.ts +146 -0
  220. package/dist/i18n/KitMessages.js +1 -0
  221. package/dist/i18n/messages/enUS.d.ts +3 -0
  222. package/dist/i18n/messages/enUS.js +112 -0
  223. package/dist/i18n/messages/enUS.js.map +1 -0
  224. package/dist/i18n/messages/ptBR.d.ts +3 -0
  225. package/dist/i18n/messages/ptBR.js +97 -0
  226. package/dist/i18n/messages/ptBR.js.map +1 -0
  227. package/dist/i18n/resolveMessages.d.ts +13 -0
  228. package/dist/i18n/resolveMessages.js +29 -0
  229. package/dist/i18n/resolveMessages.js.map +1 -0
  230. package/dist/model/Identifiable.d.ts +7 -0
  231. package/dist/model/Identifiable.js +1 -0
  232. package/dist/provider/KitConfig.d.ts +26 -0
  233. package/dist/provider/KitConfig.js +1 -0
  234. package/dist/provider/KitContext.d.ts +9 -0
  235. package/dist/provider/KitContext.js +27 -0
  236. package/dist/provider/KitContext.js.map +1 -0
  237. package/dist/provider/KitProvider.d.ts +7 -0
  238. package/dist/provider/KitProvider.js +31 -0
  239. package/dist/provider/KitProvider.js.map +1 -0
  240. package/dist/provider/useKit.d.ts +15 -0
  241. package/dist/provider/useKit.js +28 -0
  242. package/dist/provider/useKit.js.map +1 -0
  243. package/dist/router/FormRouteSegments.d.ts +16 -0
  244. package/dist/router/FormRouteSegments.js +19 -0
  245. package/dist/router/FormRouteSegments.js.map +1 -0
  246. package/dist/router/RouterAdapter.d.ts +24 -0
  247. package/dist/router/RouterAdapter.js +1 -0
  248. package/dist/router/anchorRouter.d.ts +7 -0
  249. package/dist/router/anchorRouter.js +23 -0
  250. package/dist/router/anchorRouter.js.map +1 -0
  251. package/dist/styles/print.css +93 -0
  252. package/dist/styles.css +188 -0
  253. package/dist/util/ArrayUtil.d.ts +39 -0
  254. package/dist/util/ArrayUtil.js +48 -0
  255. package/dist/util/ArrayUtil.js.map +1 -0
  256. package/dist/util/ColorUtil.d.ts +7 -0
  257. package/dist/util/ColorUtil.js +16 -0
  258. package/dist/util/ColorUtil.js.map +1 -0
  259. package/dist/util/CompareUtil.d.ts +19 -0
  260. package/dist/util/CompareUtil.js +51 -0
  261. package/dist/util/CompareUtil.js.map +1 -0
  262. package/dist/util/DateUtil.d.ts +37 -0
  263. package/dist/util/DateUtil.js +53 -0
  264. package/dist/util/DateUtil.js.map +1 -0
  265. package/dist/util/DownloadUtil.d.ts +6 -0
  266. package/dist/util/DownloadUtil.js +25 -0
  267. package/dist/util/DownloadUtil.js.map +1 -0
  268. package/dist/util/EnumUtil.d.ts +19 -0
  269. package/dist/util/EnumUtil.js +32 -0
  270. package/dist/util/EnumUtil.js.map +1 -0
  271. package/dist/util/FormUtil.d.ts +8 -0
  272. package/dist/util/FormUtil.js +14 -0
  273. package/dist/util/FormUtil.js.map +1 -0
  274. package/dist/util/HtmlUtil.d.ts +8 -0
  275. package/dist/util/HtmlUtil.js +23 -0
  276. package/dist/util/HtmlUtil.js.map +1 -0
  277. package/dist/util/Notifications.d.ts +30 -0
  278. package/dist/util/Notifications.js +59 -0
  279. package/dist/util/Notifications.js.map +1 -0
  280. package/dist/util/NumberUtil.d.ts +19 -0
  281. package/dist/util/NumberUtil.js +33 -0
  282. package/dist/util/NumberUtil.js.map +1 -0
  283. package/dist/util/ObjectUtil.d.ts +22 -0
  284. package/dist/util/ObjectUtil.js +34 -0
  285. package/dist/util/ObjectUtil.js.map +1 -0
  286. package/dist/util/SearchParamsUtil.d.ts +23 -0
  287. package/dist/util/SearchParamsUtil.js +29 -0
  288. package/dist/util/SearchParamsUtil.js.map +1 -0
  289. package/dist/util/TransformData.d.ts +14 -0
  290. package/dist/util/TransformData.js +31 -0
  291. package/dist/util/TransformData.js.map +1 -0
  292. package/dist/util/ValidationUtil.d.ts +9 -0
  293. package/dist/util/ValidationUtil.js +16 -0
  294. package/dist/util/ValidationUtil.js.map +1 -0
  295. package/dist/util/parseActionsPageParams.d.ts +14 -0
  296. package/dist/util/parseActionsPageParams.js +29 -0
  297. package/dist/util/parseActionsPageParams.js.map +1 -0
  298. package/package.json +149 -5
@@ -0,0 +1,105 @@
1
+ "use client";
2
+ import { DEFAULT_MESSAGES } from "../../../../i18n/resolveMessages.js";
3
+ // src/component/organism/EChart/chart/ChartHeader.ts
4
+ /**
5
+ * Parts of the `option` shared by all chart types: title, legend, image export and tooltip format.
6
+ * @author Manoel Campos
7
+ */
8
+ /** Distance from the legend to the top of the chart, just below the title (px). */
9
+ var LEGEND_TOP = 40;
10
+ /** Font of the names in the legend (default ECharts size and family). */
11
+ var LEGEND_FONT = "12px sans-serif";
12
+ /** Width of the icon of each legend item plus the space until the name (px). */
13
+ var LEGEND_ICON_WIDTH = 30;
14
+ /** Space between the legend items, in the same row and between rows (px). */
15
+ var LEGEND_ITEM_GAP = 8;
16
+ /** Height of each legend row, including the space until the next one (px). */
17
+ var LEGEND_ROW_HEIGHT = 22;
18
+ /** Average width of a character of the {@link LEGEND_FONT}, used when the text cannot be measured (px). */
19
+ var AVERAGE_CHAR_WIDTH = 7;
20
+ /** Text shown in the tooltip when the series has no value in the category. */
21
+ var MISSING_VALUE = "-";
22
+ /**
23
+ * Builds the title, the legend and the image export button.
24
+ * The title also appears in the saved image, so it has context outside the screen.
25
+ * @param title title of the chart
26
+ * @param names names of the series, shown in the legend
27
+ * @param messages texts of the chart; defaults to the one of the default locales
28
+ * @return the parts of the `option` of the header
29
+ */
30
+ function buildChartHeader(title, names, messages = DEFAULT_MESSAGES.chart) {
31
+ return {
32
+ title: {
33
+ text: title,
34
+ left: "left"
35
+ },
36
+ legend: {
37
+ type: "plain",
38
+ top: LEGEND_TOP,
39
+ data: names
40
+ },
41
+ toolbox: { feature: { saveAsImage: {
42
+ title: messages.saveAsImage,
43
+ name: title
44
+ } } }
45
+ };
46
+ }
47
+ /**
48
+ * Creates the function that formats a value in the tooltip with the unit of the series.
49
+ * @param unit unit of the series
50
+ * @return a function that formats the value received from ECharts (or "-" when the category has no value)
51
+ */
52
+ function tooltipFormatter(unit) {
53
+ return (value) => typeof value === "number" ? unit.format(value) : MISSING_VALUE;
54
+ }
55
+ /**
56
+ * Computes the extra height the legend takes when it wraps in more than one row, so the chart is moved down and is
57
+ * not drawn under it.
58
+ * @param names names of the series, shown in the legend
59
+ * @param width width of the chart (px); absent while unknown, considering the legend in one row
60
+ * @return the height of the legend rows beyond the first one (px)
61
+ */
62
+ function legendExtraHeight(names, width) {
63
+ return (legendRows(names, width) - 1) * 22;
64
+ }
65
+ /**
66
+ * Estimates in how many rows the legend wraps, placing the items as ECharts does: from left to right, moving to the
67
+ * next row when the next item does not fit.
68
+ * @param names names of the series, shown in the legend
69
+ * @param width width of the chart (px); absent while unknown
70
+ * @return the number of rows of the legend (at least 1)
71
+ */
72
+ function legendRows(names, width) {
73
+ if (!width) return 1;
74
+ const maxWidth = width - 10;
75
+ let rows = 1;
76
+ let rowWidth = 0;
77
+ names.forEach((name) => {
78
+ const itemWidth = LEGEND_ICON_WIDTH + textWidth(name);
79
+ const widthWithItem = rowWidth + LEGEND_ITEM_GAP + itemWidth;
80
+ if (rowWidth === 0 || widthWithItem <= maxWidth) {
81
+ rowWidth = rowWidth === 0 ? itemWidth : widthWithItem;
82
+ return;
83
+ }
84
+ rows++;
85
+ rowWidth = itemWidth;
86
+ });
87
+ return rows;
88
+ }
89
+ /** 2D context used only to measure texts; `null` where there is no canvas (server rendering, tests). */
90
+ var measureContext;
91
+ /**
92
+ * Measures the width of a text in the font of the legend. Without a canvas, estimates it from the number of characters.
93
+ * @param text text to measure
94
+ * @return the width of the text (px)
95
+ */
96
+ function textWidth(text) {
97
+ if (measureContext === void 0) {
98
+ measureContext = typeof OffscreenCanvas === "undefined" ? null : new OffscreenCanvas(1, 1).getContext("2d");
99
+ if (measureContext) measureContext.font = LEGEND_FONT;
100
+ }
101
+ return measureContext ? measureContext.measureText(text).width : text.length * AVERAGE_CHAR_WIDTH;
102
+ }
103
+ export { LEGEND_ROW_HEIGHT, buildChartHeader, legendExtraHeight, legendRows, tooltipFormatter };
104
+
105
+ //# sourceMappingURL=ChartHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartHeader.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/ChartHeader.ts"],"sourcesContent":["import type { EChartsOption } from 'echarts';\n\nimport { ChartMessages } from '../../../../i18n/KitMessages';\nimport { DEFAULT_MESSAGES } from '../../../../i18n/resolveMessages';\nimport { ChartUnit } from './ChartSeries';\n\n/**\n * Parts of the `option` shared by all chart types: title, legend, image export and tooltip format.\n * @author Manoel Campos\n */\n\n/** Distance from the legend to the top of the chart, just below the title (px). */\nconst LEGEND_TOP = 40;\n\n/*\n * Measures of the ECharts legend (its default values), used to estimate in how many rows it wraps.\n * ECharts reserves no room for the rows of the legend: whatever is drawn below it needs to know its height.\n */\n\n/** Font of the names in the legend (default ECharts size and family). */\nconst LEGEND_FONT = '12px sans-serif';\n\n/** Width of the icon of each legend item plus the space until the name (px). */\nconst LEGEND_ICON_WIDTH = 25 + 5;\n\n/** Space between the legend items, in the same row and between rows (px). */\nconst LEGEND_ITEM_GAP = 8;\n\n/** Inner padding of the legend on each side (px). */\nconst LEGEND_PADDING = 5;\n\n/** Height of each legend row, including the space until the next one (px). */\nexport const LEGEND_ROW_HEIGHT = 14 + LEGEND_ITEM_GAP;\n\n/** Average width of a character of the {@link LEGEND_FONT}, used when the text cannot be measured (px). */\nconst AVERAGE_CHAR_WIDTH = 7;\n\n/** Text shown in the tooltip when the series has no value in the category. */\nconst MISSING_VALUE = '-';\n\n/**\n * Builds the title, the legend and the image export button.\n * The title also appears in the saved image, so it has context outside the screen.\n * @param title title of the chart\n * @param names names of the series, shown in the legend\n * @param messages texts of the chart; defaults to the one of the default locales\n * @return the parts of the `option` of the header\n */\nexport function buildChartHeader(\n title: string,\n names: string[],\n messages: ChartMessages = DEFAULT_MESSAGES.chart\n): Pick<EChartsOption, 'title' | 'legend' | 'toolbox'> {\n return {\n title: { text: title, left: 'left' },\n // 'plain' wraps the legend in rows, instead of scrolling horizontally with arrows.\n legend: { type: 'plain', top: LEGEND_TOP, data: names },\n toolbox: { feature: { saveAsImage: { title: messages.saveAsImage, name: title } } }\n };\n}\n\n/**\n * Creates the function that formats a value in the tooltip with the unit of the series.\n * @param unit unit of the series\n * @return a function that formats the value received from ECharts (or \"-\" when the category has no value)\n */\nexport function tooltipFormatter(unit: ChartUnit): (value: unknown) => string {\n return value => (typeof value === 'number' ? unit.format(value) : MISSING_VALUE);\n}\n\n/**\n * Computes the extra height the legend takes when it wraps in more than one row, so the chart is moved down and is\n * not drawn under it.\n * @param names names of the series, shown in the legend\n * @param width width of the chart (px); absent while unknown, considering the legend in one row\n * @return the height of the legend rows beyond the first one (px)\n */\nexport function legendExtraHeight(names: string[], width?: number): number {\n return (legendRows(names, width) - 1) * LEGEND_ROW_HEIGHT;\n}\n\n/**\n * Estimates in how many rows the legend wraps, placing the items as ECharts does: from left to right, moving to the\n * next row when the next item does not fit.\n * @param names names of the series, shown in the legend\n * @param width width of the chart (px); absent while unknown\n * @return the number of rows of the legend (at least 1)\n */\nexport function legendRows(names: string[], width?: number): number {\n if (!width) return 1;\n\n const maxWidth = width - 2 * LEGEND_PADDING;\n let rows = 1;\n let rowWidth = 0;\n names.forEach(name => {\n const itemWidth = LEGEND_ICON_WIDTH + textWidth(name);\n const widthWithItem = rowWidth + LEGEND_ITEM_GAP + itemWidth;\n // The first item of a row always stays in it, even if it is wider than the chart.\n if (rowWidth === 0 || widthWithItem <= maxWidth) {\n rowWidth = rowWidth === 0 ? itemWidth : widthWithItem;\n return;\n }\n\n rows++;\n rowWidth = itemWidth;\n });\n\n return rows;\n}\n\n/** 2D context used only to measure texts; `null` where there is no canvas (server rendering, tests). */\nlet measureContext: OffscreenCanvasRenderingContext2D | null | undefined;\n\n/**\n * Measures the width of a text in the font of the legend. Without a canvas, estimates it from the number of characters.\n * @param text text to measure\n * @return the width of the text (px)\n */\nfunction textWidth(text: string): number {\n if (measureContext === undefined) {\n measureContext = typeof OffscreenCanvas === 'undefined' ? null : new OffscreenCanvas(1, 1).getContext('2d');\n if (measureContext) measureContext.font = LEGEND_FONT;\n }\n\n return measureContext ? measureContext.measureText(text).width : text.length * AVERAGE_CHAR_WIDTH;\n}\n"],"mappings":";;;;;;;;AAYA,IAAM,aAAa;;AAQnB,IAAM,cAAc;;AAGpB,IAAM,oBAAoB;;AAG1B,IAAM,kBAAkB;;AAMxB,IAAa,oBAAoB;;AAGjC,IAAM,qBAAqB;;AAG3B,IAAM,gBAAgB;;;;;;;;;AAUtB,SAAgB,iBACZ,OACA,OACA,WAA0B,iBAAiB,OACQ;CACnD,OAAO;EACH,OAAO;GAAE,MAAM;GAAO,MAAM;EAAO;EAEnC,QAAQ;GAAE,MAAM;GAAS,KAAK;GAAY,MAAM;EAAM;EACtD,SAAS,EAAE,SAAS,EAAE,aAAa;GAAE,OAAO,SAAS;GAAa,MAAM;EAAM,EAAE,EAAE;CACtF;AACJ;;;;;;AAOA,SAAgB,iBAAiB,MAA6C;CAC1E,QAAO,UAAU,OAAO,UAAU,WAAW,KAAK,OAAO,KAAK,IAAI;AACtE;;;;;;;;AASA,SAAgB,kBAAkB,OAAiB,OAAwB;CACvE,QAAQ,WAAW,OAAO,KAAK,IAAI,KAAA;AACvC;;;;;;;;AASA,SAAgB,WAAW,OAAiB,OAAwB;CAChE,IAAI,CAAC,OAAO,OAAO;CAEnB,MAAM,WAAW,QAAQ;CACzB,IAAI,OAAO;CACX,IAAI,WAAW;CACf,MAAM,SAAQ,SAAQ;EAClB,MAAM,YAAY,oBAAoB,UAAU,IAAI;EACpD,MAAM,gBAAgB,WAAW,kBAAkB;EAEnD,IAAI,aAAa,KAAK,iBAAiB,UAAU;GAC7C,WAAW,aAAa,IAAI,YAAY;GACxC;EACJ;EAEA;EACA,WAAW;CACf,CAAC;CAED,OAAO;AACX;;AAGA,IAAI;;;;;;AAOJ,SAAS,UAAU,MAAsB;CACrC,IAAI,mBAAmB,KAAA,GAAW;EAC9B,iBAAiB,OAAO,oBAAoB,cAAc,OAAO,IAAI,gBAAgB,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI;EAC1G,IAAI,gBAAgB,eAAe,OAAO;CAC9C;CAEA,OAAO,iBAAiB,eAAe,YAAY,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS;AACnF"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Generic data of a chart with a category axis (e.g. years), independent of any domain.
3
+ * Each app converts its data to these types and chooses a `ChartType` to build the ECharts `option`.
4
+ * @author Manoel Campos
5
+ */
6
+ /** Minimum number of series in a stack for stacking them (or splitting them in a donut) to make sense. */
7
+ export declare const MIN_STACK_SIZE = 2;
8
+ /** Unit of the values of a series: how it appears in the axis and how each value is formatted. */
9
+ export type ChartUnit = {
10
+ /** Label of the unit, shown as the name of the Y axis (e.g. "$", "m³/year"). Series with the same label share the axis. */
11
+ label: string;
12
+ /**
13
+ * Formats a value of the series for the tooltip and for the total of the donut.
14
+ * @param value value of the series
15
+ * @return the formatted value, with the suffix of the unit, if any
16
+ */
17
+ format: (value: number) => string;
18
+ };
19
+ /** Values of a series along the categories of the chart. */
20
+ export type ChartSeries = {
21
+ /** Identifies the series uniquely in the chart. */
22
+ id: string;
23
+ /** Name shown in the legend and in the tooltip (it must be unique in the chart). */
24
+ name: string;
25
+ /** One value per category, in the order of {@link ChartData#categories}; `null` when there is no value. */
26
+ values: (number | null)[];
27
+ unit: ChartUnit;
28
+ /**
29
+ * Key of the stack of the series. Series with the same key are parts of the same whole and can be stacked (or
30
+ * shown as slices of a donut). Absent when the series cannot be stacked (e.g. a total).
31
+ */
32
+ stack?: string;
33
+ /**
34
+ * Key of the stack whose total (the sum of the series of the stack) this series is. Absent when the series is not
35
+ * the total of a stack. It allows the donut to accept the total (already shown as the subtitle) without silently
36
+ * dropping other series.
37
+ */
38
+ totalOf?: string;
39
+ };
40
+ /** Series of a chart and the categories of the X axis (e.g. years), to which the values of the series are aligned. */
41
+ export type ChartData = {
42
+ categories: (string | number)[];
43
+ series: ChartSeries[];
44
+ };
45
+ /**
46
+ * Groups the series by the stack they belong to.
47
+ * @param series series of the chart
48
+ * @return the series of each stack with at least {@link MIN_STACK_SIZE} series, indexed by the key of the stack
49
+ */
50
+ export declare function groupByStack(series: ChartSeries[]): Map<string, ChartSeries[]>;
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ // src/component/organism/EChart/chart/ChartSeries.ts
3
+ /**
4
+ * Generic data of a chart with a category axis (e.g. years), independent of any domain.
5
+ * Each app converts its data to these types and chooses a `ChartType` to build the ECharts `option`.
6
+ * @author Manoel Campos
7
+ */
8
+ /** Minimum number of series in a stack for stacking them (or splitting them in a donut) to make sense. */
9
+ var MIN_STACK_SIZE = 2;
10
+ /**
11
+ * Groups the series by the stack they belong to.
12
+ * @param series series of the chart
13
+ * @return the series of each stack with at least {@link MIN_STACK_SIZE} series, indexed by the key of the stack
14
+ */
15
+ function groupByStack(series) {
16
+ const stacks = /* @__PURE__ */ new Map();
17
+ series.forEach((serie) => serie.stack && stacks.set(serie.stack, [...stacks.get(serie.stack) ?? [], serie]));
18
+ stacks.forEach((stackSeries, stack) => stackSeries.length < 2 && stacks.delete(stack));
19
+ return stacks;
20
+ }
21
+ export { MIN_STACK_SIZE, groupByStack };
22
+
23
+ //# sourceMappingURL=ChartSeries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartSeries.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/ChartSeries.ts"],"sourcesContent":["/**\n * Generic data of a chart with a category axis (e.g. years), independent of any domain.\n * Each app converts its data to these types and chooses a `ChartType` to build the ECharts `option`.\n * @author Manoel Campos\n */\n\n/** Minimum number of series in a stack for stacking them (or splitting them in a donut) to make sense. */\nexport const MIN_STACK_SIZE = 2;\n\n/** Unit of the values of a series: how it appears in the axis and how each value is formatted. */\nexport type ChartUnit = {\n /** Label of the unit, shown as the name of the Y axis (e.g. \"$\", \"m³/year\"). Series with the same label share the axis. */\n label: string;\n\n /**\n * Formats a value of the series for the tooltip and for the total of the donut.\n * @param value value of the series\n * @return the formatted value, with the suffix of the unit, if any\n */\n format: (value: number) => string;\n};\n\n/** Values of a series along the categories of the chart. */\nexport type ChartSeries = {\n /** Identifies the series uniquely in the chart. */\n id: string;\n\n /** Name shown in the legend and in the tooltip (it must be unique in the chart). */\n name: string;\n\n /** One value per category, in the order of {@link ChartData#categories}; `null` when there is no value. */\n values: (number | null)[];\n\n unit: ChartUnit;\n\n /**\n * Key of the stack of the series. Series with the same key are parts of the same whole and can be stacked (or\n * shown as slices of a donut). Absent when the series cannot be stacked (e.g. a total).\n */\n stack?: string;\n\n /**\n * Key of the stack whose total (the sum of the series of the stack) this series is. Absent when the series is not\n * the total of a stack. It allows the donut to accept the total (already shown as the subtitle) without silently\n * dropping other series.\n */\n totalOf?: string;\n};\n\n/** Series of a chart and the categories of the X axis (e.g. years), to which the values of the series are aligned. */\nexport type ChartData = {\n categories: (string | number)[];\n series: ChartSeries[];\n};\n\n/**\n * Groups the series by the stack they belong to.\n * @param series series of the chart\n * @return the series of each stack with at least {@link MIN_STACK_SIZE} series, indexed by the key of the stack\n */\nexport function groupByStack(series: ChartSeries[]): Map<string, ChartSeries[]> {\n const stacks = new Map<string, ChartSeries[]>();\n series.forEach(serie => serie.stack && stacks.set(serie.stack, [...(stacks.get(serie.stack) ?? []), serie]));\n\n stacks.forEach((stackSeries, stack) => stackSeries.length < MIN_STACK_SIZE && stacks.delete(stack));\n return stacks;\n}\n"],"mappings":";;;;;;;;AAOA,IAAa,iBAAiB;;;;;;AAqD9B,SAAgB,aAAa,QAAmD;CAC5E,MAAM,yBAAS,IAAI,IAA2B;CAC9C,OAAO,SAAQ,UAAS,MAAM,SAAS,OAAO,IAAI,MAAM,OAAO,CAAC,GAAI,OAAO,IAAI,MAAM,KAAK,KAAK,CAAC,GAAI,KAAK,CAAC,CAAC;CAE3G,OAAO,SAAS,aAAa,UAAU,YAAY,SAAA,KAA2B,OAAO,OAAO,KAAK,CAAC;CAClG,OAAO;AACX"}
@@ -0,0 +1,12 @@
1
+ import { ChartMessages } from '../../../../i18n/KitMessages';
2
+ import { ChartContext } from './ChartType';
3
+ /**
4
+ * Returns the texts of a chart: the ones of its locale, with the ones the context overrides.
5
+ * @param context context of the chart
6
+ */
7
+ export declare function chartMessages(context: Pick<ChartContext, 'locale' | 'messages'>): ChartMessages;
8
+ /**
9
+ * Returns the locale of a chart.
10
+ * @param context context of the chart
11
+ */
12
+ export declare function chartLocale(context: Pick<ChartContext, 'locale'>): string;
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import "../../../../i18n/KitLocale.js";
3
+ import { resolveMessages } from "../../../../i18n/resolveMessages.js";
4
+ // src/component/organism/EChart/chart/ChartTexts.ts
5
+ /**
6
+ * Returns the texts of a chart: the ones of its locale, with the ones the context overrides.
7
+ * @param context context of the chart
8
+ */
9
+ function chartMessages(context) {
10
+ return resolveMessages(context.locale, { chart: context.messages }).chart;
11
+ }
12
+ /**
13
+ * Returns the locale of a chart.
14
+ * @param context context of the chart
15
+ */
16
+ function chartLocale(context) {
17
+ return context.locale ?? "en-US";
18
+ }
19
+ export { chartLocale, chartMessages };
20
+
21
+ //# sourceMappingURL=ChartTexts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartTexts.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/ChartTexts.ts"],"sourcesContent":["import { DEFAULT_LOCALE } from '../../../../i18n/KitLocale';\nimport { ChartMessages } from '../../../../i18n/KitMessages';\nimport { resolveMessages } from '../../../../i18n/resolveMessages';\nimport { ChartContext } from './ChartType';\n\n/**\n * Returns the texts of a chart: the ones of its locale, with the ones the context overrides.\n * @param context context of the chart\n */\nexport function chartMessages(context: Pick<ChartContext, 'locale' | 'messages'>): ChartMessages {\n return resolveMessages(context.locale, { chart: context.messages }).chart;\n}\n\n/**\n * Returns the locale of a chart.\n * @param context context of the chart\n */\nexport function chartLocale(context: Pick<ChartContext, 'locale'>): string {\n return context.locale ?? DEFAULT_LOCALE;\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,cAAc,SAAmE;CAC7F,OAAO,gBAAgB,QAAQ,QAAQ,EAAE,OAAO,QAAQ,SAAS,CAAC,CAAC,CAAC;AACxE;;;;;AAMA,SAAgB,YAAY,SAA+C;CACvE,OAAO,QAAQ,UAAA;AACnB"}
@@ -0,0 +1,50 @@
1
+ import type { EChartsOption } from 'echarts';
2
+ import { KitLocale } from '../../../../i18n/KitLocale';
3
+ import { ChartMessages } from '../../../../i18n/KitMessages';
4
+ import { ChartData, ChartSeries } from './ChartSeries';
5
+ import { ChartTypeId } from './ChartTypeId';
6
+ /**
7
+ * Contract every chart type must follow (Strategy pattern). Each type builds the ECharts `option` from generic data
8
+ * ({@link ChartData}), depending on no domain. The name of each type, shown to the user, is in the texts of the
9
+ * locale (`chart.types[id]`).
10
+ * @author Manoel Campos
11
+ */
12
+ export type { ChartTypeId };
13
+ /** Information of the screen that affects how the chart is built, besides the data. */
14
+ export type ChartContext = {
15
+ /** Title shown in the chart (and in the saved image). */
16
+ title: string;
17
+ /** Category shown by the types that show a single category (e.g. the year of the donut); absent for the last one. */
18
+ category?: string | number;
19
+ /** Width of the chart (px), used to know in how many rows the legend wraps; absent while unknown. */
20
+ width?: number;
21
+ /** Locale of the texts and of the number format of the chart. Default: `en-US`. */
22
+ locale?: KitLocale;
23
+ /** Texts that replace the ones of the locale (e.g. the ones the app overrides in the `KitProvider`). */
24
+ messages?: Partial<ChartMessages>;
25
+ };
26
+ export interface ChartType {
27
+ readonly id: ChartTypeId;
28
+ /** Whether the type shows a single category (so the screen should show a category selector, such as the year). */
29
+ readonly singleCategory: boolean;
30
+ /**
31
+ * Tells whether the type makes sense for the series. The screen should offer only the available types.
32
+ * @param series series of the chart
33
+ * @return true if the type can be used for the series
34
+ */
35
+ isAvailable(series: ChartSeries[]): boolean;
36
+ /**
37
+ * Builds the ECharts `option`, which is given to the `EChart` component.
38
+ * @param data series and categories of the chart
39
+ * @param context title, category, locale and texts
40
+ * @return the `option` of the chart
41
+ */
42
+ buildOption(data: ChartData, context: ChartContext): EChartsOption;
43
+ /**
44
+ * Computes the height the chart needs.
45
+ * @param data series and categories of the chart
46
+ * @param context width of the chart, which defines how many rows the legend takes
47
+ * @return the height of the chart (px)
48
+ */
49
+ height(data: ChartData, context: ChartContext): number;
50
+ }
@@ -0,0 +1 @@
1
+ "use client";
@@ -0,0 +1,2 @@
1
+ /** Ids of the chart types, used as the value in a chart type selector and as the key of their names in the texts. */
2
+ export type ChartTypeId = 'line' | 'bar' | 'stacked-bar' | 'donut';
@@ -0,0 +1 @@
1
+ "use client";
@@ -0,0 +1,15 @@
1
+ import { ChartType } from './ChartType';
2
+ import { BarChart } from './BarChart';
3
+ import { LineChart } from './LineChart';
4
+ import { StackedBarChart } from './StackedBarChart';
5
+ import { DonutChart } from './DonutChart';
6
+ /**
7
+ * Single instances of the chart types. The types have no state, so they can be shared by all screens.
8
+ * @author Manoel Campos
9
+ */
10
+ export declare const LINE_CHART: LineChart;
11
+ export declare const BAR_CHART: BarChart;
12
+ export declare const STACKED_BAR_CHART: StackedBarChart;
13
+ export declare const DONUT_CHART: DonutChart;
14
+ /** All chart types, in the order they appear in a chart type selector. */
15
+ export declare const CHART_TYPES: readonly ChartType[];
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { BarChart } from "./BarChart.js";
3
+ import { LineChart } from "./LineChart.js";
4
+ import { StackedBarChart } from "./StackedBarChart.js";
5
+ import { DonutChart } from "./DonutChart.js";
6
+ // src/component/organism/EChart/chart/ChartTypes.ts
7
+ /**
8
+ * Single instances of the chart types. The types have no state, so they can be shared by all screens.
9
+ * @author Manoel Campos
10
+ */
11
+ var LINE_CHART = new LineChart();
12
+ var BAR_CHART = new BarChart();
13
+ var STACKED_BAR_CHART = new StackedBarChart();
14
+ var DONUT_CHART = new DonutChart();
15
+ /** All chart types, in the order they appear in a chart type selector. */
16
+ var CHART_TYPES = [
17
+ BAR_CHART,
18
+ LINE_CHART,
19
+ STACKED_BAR_CHART,
20
+ DONUT_CHART
21
+ ];
22
+ export { BAR_CHART, CHART_TYPES, DONUT_CHART, LINE_CHART, STACKED_BAR_CHART };
23
+
24
+ //# sourceMappingURL=ChartTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartTypes.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/ChartTypes.ts"],"sourcesContent":["import { ChartType } from './ChartType';\nimport { BarChart } from './BarChart';\nimport { LineChart } from './LineChart';\nimport { StackedBarChart } from './StackedBarChart';\nimport { DonutChart } from './DonutChart';\n\n/**\n * Single instances of the chart types. The types have no state, so they can be shared by all screens.\n * @author Manoel Campos\n */\n\nexport const LINE_CHART = new LineChart();\nexport const BAR_CHART = new BarChart();\nexport const STACKED_BAR_CHART = new StackedBarChart();\nexport const DONUT_CHART = new DonutChart();\n\n/** All chart types, in the order they appear in a chart type selector. */\nexport const CHART_TYPES: readonly ChartType[] = [BAR_CHART, LINE_CHART, STACKED_BAR_CHART, DONUT_CHART];\n"],"mappings":";;;;;;;;;;AAWA,IAAa,aAAa,IAAI,UAAU;AACxC,IAAa,YAAY,IAAI,SAAS;AACtC,IAAa,oBAAoB,IAAI,gBAAgB;AACrD,IAAa,cAAc,IAAI,WAAW;;AAG1C,IAAa,cAAoC;CAAC;CAAW;CAAY;CAAmB;AAAW"}
@@ -0,0 +1,32 @@
1
+ import type { EChartsOption } from 'echarts';
2
+ import { ChartData, ChartSeries } from './ChartSeries';
3
+ import { ChartContext, ChartType } from './ChartType';
4
+ import { ChartTypeId } from './ChartTypeId';
5
+ /**
6
+ * Height of the donut chart with the legend in one row (px). It does not depend on the number of categories; it only
7
+ * grows when the legend wraps in more rows.
8
+ */
9
+ export declare const DONUT_HEIGHT = 520;
10
+ /**
11
+ * Donut chart: shows how the total of a stack ({@link ChartSeries#stack}) splits among its series in a single
12
+ * category (e.g. "how the revenue splits by category in 2040").
13
+ * It is available only when there is exactly one stack, none of its series has a negative value (negative slices make
14
+ * no sense) and all series of the chart are in the stack or are its total ({@link ChartSeries#totalOf}).
15
+ * So choosing the donut never stops showing, without warning, a series the user selected.
16
+ * @author Manoel Campos
17
+ */
18
+ export declare class DonutChart implements ChartType {
19
+ readonly id: ChartTypeId;
20
+ readonly singleCategory = true;
21
+ isAvailable(series: ChartSeries[]): boolean;
22
+ buildOption(data: ChartData, context: ChartContext): EChartsOption;
23
+ height(data: ChartData, context: ChartContext): number;
24
+ }
25
+ /**
26
+ * Returns the category a single-category chart should show: the chosen one, if it is in the chart; otherwise, the last.
27
+ * @template C type of the categories (e.g. the years, as numbers)
28
+ * @param categories categories of the chart
29
+ * @param chosen category chosen on the screen; absent if none was chosen
30
+ * @return the category to show
31
+ */
32
+ export declare function shownCategory<C extends string | number>(categories: C[], chosen?: C): C;
@@ -0,0 +1,111 @@
1
+ "use client";
2
+ import { groupByStack } from "./ChartSeries.js";
3
+ import { chartMessages } from "./ChartTexts.js";
4
+ import { buildChartHeader, legendExtraHeight, tooltipFormatter } from "./ChartHeader.js";
5
+ // src/component/organism/EChart/chart/DonutChart.ts
6
+ /**
7
+ * Height of the donut chart with the legend in one row (px). It does not depend on the number of categories; it only
8
+ * grows when the legend wraps in more rows.
9
+ */
10
+ var DONUT_HEIGHT = 520;
11
+ /** Inner and outer radius of the donut, relative to the area of the donut ({@link DONUT_HEIGHT} high). */
12
+ var DONUT_RADIUS = ["40%", "68%"];
13
+ /** Center of the donut: moved down so it is not under the title. */
14
+ var DONUT_CENTER = ["50%", "58%"];
15
+ /**
16
+ * Donut chart: shows how the total of a stack ({@link ChartSeries#stack}) splits among its series in a single
17
+ * category (e.g. "how the revenue splits by category in 2040").
18
+ * It is available only when there is exactly one stack, none of its series has a negative value (negative slices make
19
+ * no sense) and all series of the chart are in the stack or are its total ({@link ChartSeries#totalOf}).
20
+ * So choosing the donut never stops showing, without warning, a series the user selected.
21
+ * @author Manoel Campos
22
+ */
23
+ var DonutChart = class {
24
+ id = "donut";
25
+ singleCategory = true;
26
+ isAvailable(series) {
27
+ const stacks = [...groupByStack(series).entries()];
28
+ if (stacks.length !== 1) return false;
29
+ const [stack, slicesSeries] = stacks[0];
30
+ const belongsToStack = (serie) => serie.stack === stack || serie.totalOf === stack;
31
+ return series.every(belongsToStack) && slicesSeries.every(hasNoNegativeValues);
32
+ }
33
+ buildOption(data, context) {
34
+ const messages = chartMessages(context);
35
+ const category = shownCategory(data.categories, context.category);
36
+ const slices = buildSlices(data, context);
37
+ const unit = stackSeries(data)[0]?.unit;
38
+ const total = slices.reduce((sum, slice) => sum + slice.value, 0);
39
+ const header = buildChartHeader(`${context.title} - ${category}`, slices.map((slice) => slice.name), messages);
40
+ return {
41
+ ...header,
42
+ title: {
43
+ ...header.title,
44
+ subtext: unit && messages.total(unit.format(total))
45
+ },
46
+ legend: {
47
+ ...header.legend,
48
+ top: void 0,
49
+ bottom: 0
50
+ },
51
+ tooltip: {
52
+ trigger: "item",
53
+ valueFormatter: unit && tooltipFormatter(unit)
54
+ },
55
+ series: [{
56
+ type: "pie",
57
+ top: 0,
58
+ height: 520,
59
+ radius: DONUT_RADIUS,
60
+ center: DONUT_CENTER,
61
+ data: slices,
62
+ label: { formatter: "{b}: {d}%" }
63
+ }]
64
+ };
65
+ }
66
+ height(data, context) {
67
+ return 520 + legendExtraHeight(buildSlices(data, context).map((slice) => slice.name), context.width);
68
+ }
69
+ };
70
+ /**
71
+ * Returns the series of the only stack of the chart, which become the slices of the donut.
72
+ * @param data series and categories of the chart
73
+ * @return the series of the stack (empty if there is no stack)
74
+ */
75
+ function stackSeries(data) {
76
+ return [...groupByStack(data.series).values()][0] ?? [];
77
+ }
78
+ /**
79
+ * Builds the slices of the donut in the category shown, without the series that have no value in it.
80
+ * @param data series and categories of the chart
81
+ * @param context category chosen on the screen
82
+ * @return a slice per series of the stack with a value in the category
83
+ */
84
+ function buildSlices(data, context) {
85
+ const categoryIndex = data.categories.indexOf(shownCategory(data.categories, context.category));
86
+ return stackSeries(data).map((serie) => ({
87
+ name: serie.name,
88
+ value: serie.values[categoryIndex]
89
+ })).filter((slice) => slice.value !== null);
90
+ }
91
+ /**
92
+ * Checks whether a series has no negative values, which make no sense as slices.
93
+ * @param serie series of a stack
94
+ * @return true if the series has no negative value (categories without a value are ignored)
95
+ */
96
+ function hasNoNegativeValues(serie) {
97
+ return serie.values.every((value) => value === null || value >= 0);
98
+ }
99
+ /**
100
+ * Returns the category a single-category chart should show: the chosen one, if it is in the chart; otherwise, the last.
101
+ * @template C type of the categories (e.g. the years, as numbers)
102
+ * @param categories categories of the chart
103
+ * @param chosen category chosen on the screen; absent if none was chosen
104
+ * @return the category to show
105
+ */
106
+ function shownCategory(categories, chosen) {
107
+ return chosen !== void 0 && categories.includes(chosen) ? chosen : categories[categories.length - 1];
108
+ }
109
+ export { DONUT_HEIGHT, DonutChart, shownCategory };
110
+
111
+ //# sourceMappingURL=DonutChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DonutChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/DonutChart.ts"],"sourcesContent":["import type { EChartsOption } from 'echarts';\n\nimport { ChartData, ChartSeries, groupByStack } from './ChartSeries';\nimport { ChartContext, ChartType } from './ChartType';\nimport { ChartTypeId } from './ChartTypeId';\nimport { chartMessages } from './ChartTexts';\nimport { buildChartHeader, legendExtraHeight, tooltipFormatter } from './ChartHeader';\n\n/**\n * Height of the donut chart with the legend in one row (px). It does not depend on the number of categories; it only\n * grows when the legend wraps in more rows.\n */\nexport const DONUT_HEIGHT = 520;\n\n/** Inner and outer radius of the donut, relative to the area of the donut ({@link DONUT_HEIGHT} high). */\nconst DONUT_RADIUS = ['40%', '68%'];\n\n/** Center of the donut: moved down so it is not under the title. */\nconst DONUT_CENTER = ['50%', '58%'];\n\n/**\n * Donut chart: shows how the total of a stack ({@link ChartSeries#stack}) splits among its series in a single\n * category (e.g. \"how the revenue splits by category in 2040\").\n * It is available only when there is exactly one stack, none of its series has a negative value (negative slices make\n * no sense) and all series of the chart are in the stack or are its total ({@link ChartSeries#totalOf}).\n * So choosing the donut never stops showing, without warning, a series the user selected.\n * @author Manoel Campos\n */\nexport class DonutChart implements ChartType {\n readonly id: ChartTypeId = 'donut';\n readonly singleCategory = true;\n\n isAvailable(series: ChartSeries[]): boolean {\n const stacks = [...groupByStack(series).entries()];\n if (stacks.length !== 1) return false;\n\n const [stack, slicesSeries] = stacks[0];\n const belongsToStack = (serie: ChartSeries) => serie.stack === stack || serie.totalOf === stack;\n return series.every(belongsToStack) && slicesSeries.every(hasNoNegativeValues);\n }\n\n buildOption(data: ChartData, context: ChartContext): EChartsOption {\n const messages = chartMessages(context);\n const category = shownCategory(data.categories, context.category);\n const slices = buildSlices(data, context);\n const unit = stackSeries(data)[0]?.unit;\n const total = slices.reduce((sum, slice) => sum + slice.value, 0);\n const header = buildChartHeader(\n `${context.title} - ${category}`,\n slices.map(slice => slice.name),\n messages\n );\n\n return {\n ...header,\n title: { ...header.title, subtext: unit && messages.total(unit.format(total)) },\n // The legend goes to the bottom, so it is not under the subtitle with the total.\n legend: { ...header.legend, top: undefined, bottom: 0 },\n tooltip: { trigger: 'item', valueFormatter: unit && tooltipFormatter(unit) },\n series: [\n {\n type: 'pie',\n // The area of the donut is fixed at the top; the extra legend rows stay below it.\n top: 0,\n height: DONUT_HEIGHT,\n radius: DONUT_RADIUS,\n center: DONUT_CENTER,\n data: slices,\n label: { formatter: '{b}: {d}%' }\n }\n ]\n } as EChartsOption;\n }\n\n height(data: ChartData, context: ChartContext): number {\n return (\n DONUT_HEIGHT +\n legendExtraHeight(\n buildSlices(data, context).map(slice => slice.name),\n context.width\n )\n );\n }\n}\n\n/** Slice of the donut: the value of a series of the stack in the category shown. */\ntype Slice = { name: string; value: number };\n\n/**\n * Returns the series of the only stack of the chart, which become the slices of the donut.\n * @param data series and categories of the chart\n * @return the series of the stack (empty if there is no stack)\n */\nfunction stackSeries(data: ChartData): ChartSeries[] {\n return [...groupByStack(data.series).values()][0] ?? [];\n}\n\n/**\n * Builds the slices of the donut in the category shown, without the series that have no value in it.\n * @param data series and categories of the chart\n * @param context category chosen on the screen\n * @return a slice per series of the stack with a value in the category\n */\nfunction buildSlices(data: ChartData, context: ChartContext): Slice[] {\n const categoryIndex = data.categories.indexOf(shownCategory(data.categories, context.category));\n return stackSeries(data)\n .map(serie => ({ name: serie.name, value: serie.values[categoryIndex] }))\n .filter((slice): slice is Slice => slice.value !== null);\n}\n\n/**\n * Checks whether a series has no negative values, which make no sense as slices.\n * @param serie series of a stack\n * @return true if the series has no negative value (categories without a value are ignored)\n */\nfunction hasNoNegativeValues(serie: ChartSeries): boolean {\n return serie.values.every(value => value === null || value >= 0);\n}\n\n/**\n * Returns the category a single-category chart should show: the chosen one, if it is in the chart; otherwise, the last.\n * @template C type of the categories (e.g. the years, as numbers)\n * @param categories categories of the chart\n * @param chosen category chosen on the screen; absent if none was chosen\n * @return the category to show\n */\nexport function shownCategory<C extends string | number>(categories: C[], chosen?: C): C {\n return chosen !== undefined && categories.includes(chosen) ? chosen : categories[categories.length - 1];\n}\n"],"mappings":";;;;;;;;;AAYA,IAAa,eAAe;;AAG5B,IAAM,eAAe,CAAC,OAAO,KAAK;;AAGlC,IAAM,eAAe,CAAC,OAAO,KAAK;;;;;;;;;AAUlC,IAAa,aAAb,MAA6C;CACzC,KAA2B;CAC3B,iBAA0B;CAE1B,YAAY,QAAgC;EACxC,MAAM,SAAS,CAAC,GAAG,aAAa,MAAM,CAAC,CAAC,QAAQ,CAAC;EACjD,IAAI,OAAO,WAAW,GAAG,OAAO;EAEhC,MAAM,CAAC,OAAO,gBAAgB,OAAO;EACrC,MAAM,kBAAkB,UAAuB,MAAM,UAAU,SAAS,MAAM,YAAY;EAC1F,OAAO,OAAO,MAAM,cAAc,KAAK,aAAa,MAAM,mBAAmB;CACjF;CAEA,YAAY,MAAiB,SAAsC;EAC/D,MAAM,WAAW,cAAc,OAAO;EACtC,MAAM,WAAW,cAAc,KAAK,YAAY,QAAQ,QAAQ;EAChE,MAAM,SAAS,YAAY,MAAM,OAAO;EACxC,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC,EAAE,EAAE;EACnC,MAAM,QAAQ,OAAO,QAAQ,KAAK,UAAU,MAAM,MAAM,OAAO,CAAC;EAChE,MAAM,SAAS,iBACX,GAAG,QAAQ,MAAM,KAAK,YACtB,OAAO,KAAI,UAAS,MAAM,IAAI,GAC9B,QACJ;EAEA,OAAO;GACH,GAAG;GACH,OAAO;IAAE,GAAG,OAAO;IAAO,SAAS,QAAQ,SAAS,MAAM,KAAK,OAAO,KAAK,CAAC;GAAE;GAE9E,QAAQ;IAAE,GAAG,OAAO;IAAQ,KAAK,KAAA;IAAW,QAAQ;GAAE;GACtD,SAAS;IAAE,SAAS;IAAQ,gBAAgB,QAAQ,iBAAiB,IAAI;GAAE;GAC3E,QAAQ,CACJ;IACI,MAAM;IAEN,KAAK;IACL,QAAA;IACA,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO,EAAE,WAAW,YAAY;GACpC,CACJ;EACJ;CACJ;CAEA,OAAO,MAAiB,SAA+B;EACnD,OAAA,MAEI,kBACI,YAAY,MAAM,OAAO,CAAC,CAAC,KAAI,UAAS,MAAM,IAAI,GAClD,QAAQ,KACZ;CAER;AACJ;;;;;;AAUA,SAAS,YAAY,MAAgC;CACjD,OAAO,CAAC,GAAG,aAAa,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAC1D;;;;;;;AAQA,SAAS,YAAY,MAAiB,SAAgC;CAClE,MAAM,gBAAgB,KAAK,WAAW,QAAQ,cAAc,KAAK,YAAY,QAAQ,QAAQ,CAAC;CAC9F,OAAO,YAAY,IAAI,CAAC,CACnB,KAAI,WAAU;EAAE,MAAM,MAAM;EAAM,OAAO,MAAM,OAAO;CAAe,EAAE,CAAC,CACxE,QAAQ,UAA0B,MAAM,UAAU,IAAI;AAC/D;;;;;;AAOA,SAAS,oBAAoB,OAA6B;CACtD,OAAO,MAAM,OAAO,OAAM,UAAS,UAAU,QAAQ,SAAS,CAAC;AACnE;;;;;;;;AASA,SAAgB,cAAyC,YAAiB,QAAe;CACrF,OAAO,WAAW,KAAA,KAAa,WAAW,SAAS,MAAM,IAAI,SAAS,WAAW,WAAW,SAAS;AACzG"}
@@ -0,0 +1,11 @@
1
+ import { ChartTypeId } from './ChartTypeId';
2
+ import { CartesianChart, CartesianSeries } from './CartesianChart';
3
+ /**
4
+ * Line chart: shows the trend of each series along the categories.
5
+ * Suited to rates and levels (e.g. percentages, coefficients, population).
6
+ * @author Manoel Campos
7
+ */
8
+ export declare class LineChart extends CartesianChart {
9
+ readonly id: ChartTypeId;
10
+ protected seriesStyle(): CartesianSeries;
11
+ }
@@ -0,0 +1,20 @@
1
+ "use client";
2
+ import { CartesianChart } from "./CartesianChart.js";
3
+ // src/component/organism/EChart/chart/LineChart.ts
4
+ /**
5
+ * Line chart: shows the trend of each series along the categories.
6
+ * Suited to rates and levels (e.g. percentages, coefficients, population).
7
+ * @author Manoel Campos
8
+ */
9
+ var LineChart = class extends CartesianChart {
10
+ id = "line";
11
+ seriesStyle() {
12
+ return {
13
+ type: "line",
14
+ connectNulls: false
15
+ };
16
+ }
17
+ };
18
+ export { LineChart };
19
+
20
+ //# sourceMappingURL=LineChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LineChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/LineChart.ts"],"sourcesContent":["import { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries } from './CartesianChart';\n\n/**\n * Line chart: shows the trend of each series along the categories.\n * Suited to rates and levels (e.g. percentages, coefficients, population).\n * @author Manoel Campos\n */\nexport class LineChart extends CartesianChart {\n readonly id: ChartTypeId = 'line';\n\n protected seriesStyle(): CartesianSeries {\n // connectNulls false: a category without a value is a gap in the line, instead of joining the neighbors.\n return { type: 'line', connectNulls: false };\n }\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,YAAb,cAA+B,eAAe;CAC1C,KAA2B;CAE3B,cAAyC;EAErC,OAAO;GAAE,MAAM;GAAQ,cAAc;EAAM;CAC/C;AACJ"}
@@ -0,0 +1,15 @@
1
+ import { ChartSeries } from './ChartSeries';
2
+ import { ChartTypeId } from './ChartTypeId';
3
+ import { CartesianChart, CartesianSeries } from './CartesianChart';
4
+ /**
5
+ * Stacked column chart with lines: the series of the same stack ({@link ChartSeries#stack}) are stacked, showing how
6
+ * much each one contributes to each category, and the other series (such as a total) become lines over the columns.
7
+ * It is available only when there is a stack with enough series (see `groupByStack`). Whoever builds the series
8
+ * decides which ones can be stacked, so series whose sum makes no sense are never stacked.
9
+ * @author Manoel Campos
10
+ */
11
+ export declare class StackedBarChart extends CartesianChart {
12
+ readonly id: ChartTypeId;
13
+ isAvailable(series: ChartSeries[]): boolean;
14
+ protected seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries;
15
+ }
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { groupByStack } from "./ChartSeries.js";
3
+ import { CartesianChart } from "./CartesianChart.js";
4
+ // src/component/organism/EChart/chart/StackedBarChart.ts
5
+ /**
6
+ * Stacked column chart with lines: the series of the same stack ({@link ChartSeries#stack}) are stacked, showing how
7
+ * much each one contributes to each category, and the other series (such as a total) become lines over the columns.
8
+ * It is available only when there is a stack with enough series (see `groupByStack`). Whoever builds the series
9
+ * decides which ones can be stacked, so series whose sum makes no sense are never stacked.
10
+ * @author Manoel Campos
11
+ */
12
+ var StackedBarChart = class extends CartesianChart {
13
+ id = "stacked-bar";
14
+ isAvailable(series) {
15
+ return groupByStack(series).size > 0;
16
+ }
17
+ seriesStyle(serie, all) {
18
+ if (!serie.stack || !groupByStack(all).has(serie.stack)) return {
19
+ type: "line",
20
+ connectNulls: false
21
+ };
22
+ return {
23
+ type: "bar",
24
+ stack: serie.stack
25
+ };
26
+ }
27
+ };
28
+ export { StackedBarChart };
29
+
30
+ //# sourceMappingURL=StackedBarChart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StackedBarChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/StackedBarChart.ts"],"sourcesContent":["import { ChartSeries, groupByStack } from './ChartSeries';\nimport { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries } from './CartesianChart';\n\n/**\n * Stacked column chart with lines: the series of the same stack ({@link ChartSeries#stack}) are stacked, showing how\n * much each one contributes to each category, and the other series (such as a total) become lines over the columns.\n * It is available only when there is a stack with enough series (see `groupByStack`). Whoever builds the series\n * decides which ones can be stacked, so series whose sum makes no sense are never stacked.\n * @author Manoel Campos\n */\nexport class StackedBarChart extends CartesianChart {\n readonly id: ChartTypeId = 'stacked-bar';\n\n isAvailable(series: ChartSeries[]): boolean {\n return groupByStack(series).size > 0;\n }\n\n protected seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries {\n // A series with a stack, but alone in it, has nothing to be stacked with: it becomes a line.\n if (!serie.stack || !groupByStack(all).has(serie.stack)) return { type: 'line', connectNulls: false };\n\n // Each stack is stacked separately, so series of different wholes are not added up.\n return { type: 'bar', stack: serie.stack };\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,IAAa,kBAAb,cAAqC,eAAe;CAChD,KAA2B;CAE3B,YAAY,QAAgC;EACxC,OAAO,aAAa,MAAM,CAAC,CAAC,OAAO;CACvC;CAEA,YAAsB,OAAoB,KAAqC;EAE3E,IAAI,CAAC,MAAM,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,MAAM,KAAK,GAAG,OAAO;GAAE,MAAM;GAAQ,cAAc;EAAM;EAGpG,OAAO;GAAE,MAAM;GAAO,OAAO,MAAM;EAAM;CAC7C;AACJ"}