@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.
- package/LICENSE +21 -0
- package/README.md +471 -2
- package/dist/component/atom/AppMain/App.module.js +7 -0
- package/dist/component/atom/AppMain/App.module.js.map +1 -0
- package/dist/component/atom/AppMain/AppMain.d.ts +7 -0
- package/dist/component/atom/AppMain/AppMain.js +14 -0
- package/dist/component/atom/AppMain/AppMain.js.map +1 -0
- package/dist/component/atom/CancelEditButton/CancelEditButton.d.ts +6 -0
- package/dist/component/atom/CancelEditButton/CancelEditButton.js +24 -0
- package/dist/component/atom/CancelEditButton/CancelEditButton.js.map +1 -0
- package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.d.ts +13 -0
- package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.js +30 -0
- package/dist/component/atom/ConfirmEditButton/ConfirmEditButton.js.map +1 -0
- package/dist/component/atom/DateField/DateField.d.ts +7 -0
- package/dist/component/atom/DateField/DateField.js +21 -0
- package/dist/component/atom/DateField/DateField.js.map +1 -0
- package/dist/component/atom/EditValueButton/EditValueButton.d.ts +6 -0
- package/dist/component/atom/EditValueButton/EditValueButton.js +24 -0
- package/dist/component/atom/EditValueButton/EditValueButton.js.map +1 -0
- package/dist/component/atom/ErrorAlert/ErrorAlert.d.ts +8 -0
- package/dist/component/atom/ErrorAlert/ErrorAlert.js +21 -0
- package/dist/component/atom/ErrorAlert/ErrorAlert.js.map +1 -0
- package/dist/component/atom/Surface/Surface.d.ts +20 -0
- package/dist/component/atom/Surface/Surface.js +15 -0
- package/dist/component/atom/Surface/Surface.js.map +1 -0
- package/dist/component/molecule/Breadcrumb/Breadcrumb.d.ts +12 -0
- package/dist/component/molecule/Breadcrumb/Breadcrumb.js +38 -0
- package/dist/component/molecule/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/component/molecule/ExportMenuButton/ExportMenuButton.d.ts +25 -0
- package/dist/component/molecule/ExportMenuButton/ExportMenuButton.js +49 -0
- package/dist/component/molecule/ExportMenuButton/ExportMenuButton.js.map +1 -0
- package/dist/component/molecule/PaperCard/PaperCard.d.ts +7 -0
- package/dist/component/molecule/PaperCard/PaperCard.js +17 -0
- package/dist/component/molecule/PaperCard/PaperCard.js.map +1 -0
- package/dist/component/molecule/PrintSection/PrintSection.d.ts +14 -0
- package/dist/component/molecule/PrintSection/PrintSection.js +29 -0
- package/dist/component/molecule/PrintSection/PrintSection.js.map +1 -0
- package/dist/component/molecule/SelectField/SelectField.d.ts +32 -0
- package/dist/component/molecule/SelectField/SelectField.js +38 -0
- package/dist/component/molecule/SelectField/SelectField.js.map +1 -0
- package/dist/component/molecule/StatsCard/Stats.module.js +15 -0
- package/dist/component/molecule/StatsCard/Stats.module.js.map +1 -0
- package/dist/component/molecule/StatsCard/StatsCard.d.ts +18 -0
- package/dist/component/molecule/StatsCard/StatsCard.js +60 -0
- package/dist/component/molecule/StatsCard/StatsCard.js.map +1 -0
- package/dist/component/organism/DataForm/DataForm.d.ts +26 -0
- package/dist/component/organism/DataForm/DataForm.js +83 -0
- package/dist/component/organism/DataForm/DataForm.js.map +1 -0
- package/dist/component/organism/DataTabList/DataTabList.d.ts +24 -0
- package/dist/component/organism/DataTabList/DataTabList.js +37 -0
- package/dist/component/organism/DataTabList/DataTabList.js.map +1 -0
- package/dist/component/organism/DataTabList/DataTabList.module.js +13 -0
- package/dist/component/organism/DataTabList/DataTabList.module.js.map +1 -0
- package/dist/component/organism/EChart/EChart.d.ts +47 -0
- package/dist/component/organism/EChart/EChart.js +37 -0
- package/dist/component/organism/EChart/EChart.js.map +1 -0
- package/dist/component/organism/EChart/buildEChartOption.d.ts +40 -0
- package/dist/component/organism/EChart/buildEChartOption.js +57 -0
- package/dist/component/organism/EChart/buildEChartOption.js.map +1 -0
- package/dist/component/organism/EChart/chart/BarChart.d.ts +22 -0
- package/dist/component/organism/EChart/chart/BarChart.js +34 -0
- package/dist/component/organism/EChart/chart/BarChart.js.map +1 -0
- package/dist/component/organism/EChart/chart/CartesianChart.d.ts +48 -0
- package/dist/component/organism/EChart/chart/CartesianChart.js +63 -0
- package/dist/component/organism/EChart/chart/CartesianChart.js.map +1 -0
- package/dist/component/organism/EChart/chart/ChartHeader.d.ts +36 -0
- package/dist/component/organism/EChart/chart/ChartHeader.js +105 -0
- package/dist/component/organism/EChart/chart/ChartHeader.js.map +1 -0
- package/dist/component/organism/EChart/chart/ChartSeries.d.ts +50 -0
- package/dist/component/organism/EChart/chart/ChartSeries.js +23 -0
- package/dist/component/organism/EChart/chart/ChartSeries.js.map +1 -0
- package/dist/component/organism/EChart/chart/ChartTexts.d.ts +12 -0
- package/dist/component/organism/EChart/chart/ChartTexts.js +21 -0
- package/dist/component/organism/EChart/chart/ChartTexts.js.map +1 -0
- package/dist/component/organism/EChart/chart/ChartType.d.ts +50 -0
- package/dist/component/organism/EChart/chart/ChartType.js +1 -0
- package/dist/component/organism/EChart/chart/ChartTypeId.d.ts +2 -0
- package/dist/component/organism/EChart/chart/ChartTypeId.js +1 -0
- package/dist/component/organism/EChart/chart/ChartTypes.d.ts +15 -0
- package/dist/component/organism/EChart/chart/ChartTypes.js +24 -0
- package/dist/component/organism/EChart/chart/ChartTypes.js.map +1 -0
- package/dist/component/organism/EChart/chart/DonutChart.d.ts +32 -0
- package/dist/component/organism/EChart/chart/DonutChart.js +111 -0
- package/dist/component/organism/EChart/chart/DonutChart.js.map +1 -0
- package/dist/component/organism/EChart/chart/LineChart.d.ts +11 -0
- package/dist/component/organism/EChart/chart/LineChart.js +20 -0
- package/dist/component/organism/EChart/chart/LineChart.js.map +1 -0
- package/dist/component/organism/EChart/chart/StackedBarChart.d.ts +15 -0
- package/dist/component/organism/EChart/chart/StackedBarChart.js +30 -0
- package/dist/component/organism/EChart/chart/StackedBarChart.js.map +1 -0
- package/dist/component/organism/EChart/chart/UnitPanels.d.ts +63 -0
- package/dist/component/organism/EChart/chart/UnitPanels.js +127 -0
- package/dist/component/organism/EChart/chart/UnitPanels.js.map +1 -0
- package/dist/component/organism/EChart/echartDefaults.d.ts +32 -0
- package/dist/component/organism/EChart/echartDefaults.js +47 -0
- package/dist/component/organism/EChart/echartDefaults.js.map +1 -0
- package/dist/component/organism/EChart/useEChart.d.ts +35 -0
- package/dist/component/organism/EChart/useEChart.js +112 -0
- package/dist/component/organism/EChart/useEChart.js.map +1 -0
- package/dist/component/organism/Navbar/NavItem.d.ts +16 -0
- package/dist/component/organism/Navbar/NavItem.js +1 -0
- package/dist/component/organism/Navbar/Navbar.d.ts +20 -0
- package/dist/component/organism/Navbar/Navbar.js +64 -0
- package/dist/component/organism/Navbar/Navbar.js.map +1 -0
- package/dist/component/organism/Navbar/Navbar.module.js +19 -0
- package/dist/component/organism/Navbar/Navbar.module.js.map +1 -0
- package/dist/component/organism/PageHeader/PageHeader.d.ts +14 -0
- package/dist/component/organism/PageHeader/PageHeader.js +55 -0
- package/dist/component/organism/PageHeader/PageHeader.js.map +1 -0
- package/dist/component/organism/StatsGrid/StatsGrid.d.ts +12 -0
- package/dist/component/organism/StatsGrid/StatsGrid.js +46 -0
- package/dist/component/organism/StatsGrid/StatsGrid.js.map +1 -0
- package/dist/component/organism/StatsGrid/StatsGrid.module.js +17 -0
- package/dist/component/organism/StatsGrid/StatsGrid.module.js.map +1 -0
- package/dist/component/organism/Table/RowActions.d.ts +23 -0
- package/dist/component/organism/Table/RowActions.js +121 -0
- package/dist/component/organism/Table/RowActions.js.map +1 -0
- package/dist/component/organism/Table/Table.d.ts +51 -0
- package/dist/component/organism/Table/Table.js +108 -0
- package/dist/component/organism/Table/Table.js.map +1 -0
- package/dist/component/organism/ViewTable/ColumnComparator.d.ts +11 -0
- package/dist/component/organism/ViewTable/ColumnComparator.js +25 -0
- package/dist/component/organism/ViewTable/ColumnComparator.js.map +1 -0
- package/dist/component/organism/ViewTable/ViewTable.d.ts +53 -0
- package/dist/component/organism/ViewTable/ViewTable.js +123 -0
- package/dist/component/organism/ViewTable/ViewTable.js.map +1 -0
- package/dist/component/template/CreateFormPage/CreateFormPage.d.ts +19 -0
- package/dist/component/template/CreateFormPage/CreateFormPage.js +41 -0
- package/dist/component/template/CreateFormPage/CreateFormPage.js.map +1 -0
- package/dist/component/template/EditFormPage/EditFormPage.d.ts +19 -0
- package/dist/component/template/EditFormPage/EditFormPage.js +42 -0
- package/dist/component/template/EditFormPage/EditFormPage.js.map +1 -0
- package/dist/component/template/FormPage/FormPage.d.ts +25 -0
- package/dist/component/template/FormPage/FormPage.js +130 -0
- package/dist/component/template/FormPage/FormPage.js.map +1 -0
- package/dist/component/template/FormPage/FormType.d.ts +6 -0
- package/dist/component/template/FormPage/FormType.js +12 -0
- package/dist/component/template/FormPage/FormType.js.map +1 -0
- package/dist/component/template/Layout/Layout.d.ts +21 -0
- package/dist/component/template/Layout/Layout.js +121 -0
- package/dist/component/template/Layout/Layout.js.map +1 -0
- package/dist/component/template/Layout/Layout.module.js +19 -0
- package/dist/component/template/Layout/Layout.module.js.map +1 -0
- package/dist/component/template/ListPage/ListPage.d.ts +32 -0
- package/dist/component/template/ListPage/ListPage.js +47 -0
- package/dist/component/template/ListPage/ListPage.js.map +1 -0
- package/dist/component/template/PrintPage/PrintPage.d.ts +25 -0
- package/dist/component/template/PrintPage/PrintPage.js +115 -0
- package/dist/component/template/PrintPage/PrintPage.js.map +1 -0
- package/dist/component/template/ViewPage/ViewPage.d.ts +11 -0
- package/dist/component/template/ViewPage/ViewPage.js +49 -0
- package/dist/component/template/ViewPage/ViewPage.js.map +1 -0
- package/dist/data/ListDataSource.d.ts +12 -0
- package/dist/data/ListDataSource.js +1 -0
- package/dist/data/SaveDataSource.d.ts +16 -0
- package/dist/data/SaveDataSource.js +1 -0
- package/dist/export/ExportCellText.d.ts +18 -0
- package/dist/export/ExportCellText.js +60 -0
- package/dist/export/ExportCellText.js.map +1 -0
- package/dist/export/ExportDocument.d.ts +127 -0
- package/dist/export/ExportDocument.js +59 -0
- package/dist/export/ExportDocument.js.map +1 -0
- package/dist/export/ExportDownload.d.ts +9 -0
- package/dist/export/ExportDownload.js +19 -0
- package/dist/export/ExportDownload.js.map +1 -0
- package/dist/export/ExportFileName.d.ts +11 -0
- package/dist/export/ExportFileName.js +24 -0
- package/dist/export/ExportFileName.js.map +1 -0
- package/dist/export/ExportFormat.d.ts +30 -0
- package/dist/export/ExportFormat.js +1 -0
- package/dist/export/ExportFormats.d.ts +12 -0
- package/dist/export/ExportFormats.js +16 -0
- package/dist/export/ExportFormats.js.map +1 -0
- package/dist/export/ExportTexts.d.ts +14 -0
- package/dist/export/ExportTexts.js +23 -0
- package/dist/export/ExportTexts.js.map +1 -0
- package/dist/export/csv/CsvFormat.d.ts +41 -0
- package/dist/export/csv/CsvFormat.js +91 -0
- package/dist/export/csv/CsvFormat.js.map +1 -0
- package/dist/export/xlsx/XlsxFormat.d.ts +35 -0
- package/dist/export/xlsx/XlsxFormat.js +66 -0
- package/dist/export/xlsx/XlsxFormat.js.map +1 -0
- package/dist/export/xlsx/XlsxNumberFormat.d.ts +8 -0
- package/dist/export/xlsx/XlsxNumberFormat.js +15 -0
- package/dist/export/xlsx/XlsxNumberFormat.js.map +1 -0
- package/dist/export/xlsx/XlsxSheetName.d.ts +12 -0
- package/dist/export/xlsx/XlsxSheetName.js +62 -0
- package/dist/export/xlsx/XlsxSheetName.js.map +1 -0
- package/dist/export/xlsx/XlsxSheetWriter.d.ts +67 -0
- package/dist/export/xlsx/XlsxSheetWriter.js +215 -0
- package/dist/export/xlsx/XlsxSheetWriter.js.map +1 -0
- package/dist/export/xlsx/XlsxStyle.d.ts +51 -0
- package/dist/export/xlsx/XlsxStyle.js +87 -0
- package/dist/export/xlsx/XlsxStyle.js.map +1 -0
- package/dist/hook/useIsMobile.d.ts +5 -0
- package/dist/hook/useIsMobile.js +16 -0
- package/dist/hook/useIsMobile.js.map +1 -0
- package/dist/hook/useKeyedService.d.ts +22 -0
- package/dist/hook/useKeyedService.js +38 -0
- package/dist/hook/useKeyedService.js.map +1 -0
- package/dist/hook/useLightColorSchemeOnPrint.d.ts +9 -0
- package/dist/hook/useLightColorSchemeOnPrint.js +36 -0
- package/dist/hook/useLightColorSchemeOnPrint.js.map +1 -0
- package/dist/hook/useService.d.ts +12 -0
- package/dist/hook/useService.js +29 -0
- package/dist/hook/useService.js.map +1 -0
- package/dist/http/ApiError.d.ts +13 -0
- package/dist/http/ApiError.js +22 -0
- package/dist/http/ApiError.js.map +1 -0
- package/dist/http/AxiosHttpClient.d.ts +21 -0
- package/dist/http/AxiosHttpClient.js +67 -0
- package/dist/http/AxiosHttpClient.js.map +1 -0
- package/dist/http/AxiosHttpClientConfig.d.ts +37 -0
- package/dist/http/AxiosHttpClientConfig.js +19 -0
- package/dist/http/AxiosHttpClientConfig.js.map +1 -0
- package/dist/i18n/KitLocale.d.ts +4 -0
- package/dist/i18n/KitLocale.js +7 -0
- package/dist/i18n/KitLocale.js.map +1 -0
- package/dist/i18n/KitMessages.d.ts +146 -0
- package/dist/i18n/KitMessages.js +1 -0
- package/dist/i18n/messages/enUS.d.ts +3 -0
- package/dist/i18n/messages/enUS.js +112 -0
- package/dist/i18n/messages/enUS.js.map +1 -0
- package/dist/i18n/messages/ptBR.d.ts +3 -0
- package/dist/i18n/messages/ptBR.js +97 -0
- package/dist/i18n/messages/ptBR.js.map +1 -0
- package/dist/i18n/resolveMessages.d.ts +13 -0
- package/dist/i18n/resolveMessages.js +29 -0
- package/dist/i18n/resolveMessages.js.map +1 -0
- package/dist/model/Identifiable.d.ts +7 -0
- package/dist/model/Identifiable.js +1 -0
- package/dist/provider/KitConfig.d.ts +26 -0
- package/dist/provider/KitConfig.js +1 -0
- package/dist/provider/KitContext.d.ts +9 -0
- package/dist/provider/KitContext.js +27 -0
- package/dist/provider/KitContext.js.map +1 -0
- package/dist/provider/KitProvider.d.ts +7 -0
- package/dist/provider/KitProvider.js +31 -0
- package/dist/provider/KitProvider.js.map +1 -0
- package/dist/provider/useKit.d.ts +15 -0
- package/dist/provider/useKit.js +28 -0
- package/dist/provider/useKit.js.map +1 -0
- package/dist/router/FormRouteSegments.d.ts +16 -0
- package/dist/router/FormRouteSegments.js +19 -0
- package/dist/router/FormRouteSegments.js.map +1 -0
- package/dist/router/RouterAdapter.d.ts +24 -0
- package/dist/router/RouterAdapter.js +1 -0
- package/dist/router/anchorRouter.d.ts +7 -0
- package/dist/router/anchorRouter.js +23 -0
- package/dist/router/anchorRouter.js.map +1 -0
- package/dist/styles/print.css +93 -0
- package/dist/styles.css +188 -0
- package/dist/util/ArrayUtil.d.ts +39 -0
- package/dist/util/ArrayUtil.js +48 -0
- package/dist/util/ArrayUtil.js.map +1 -0
- package/dist/util/ColorUtil.d.ts +7 -0
- package/dist/util/ColorUtil.js +16 -0
- package/dist/util/ColorUtil.js.map +1 -0
- package/dist/util/CompareUtil.d.ts +19 -0
- package/dist/util/CompareUtil.js +51 -0
- package/dist/util/CompareUtil.js.map +1 -0
- package/dist/util/DateUtil.d.ts +37 -0
- package/dist/util/DateUtil.js +53 -0
- package/dist/util/DateUtil.js.map +1 -0
- package/dist/util/DownloadUtil.d.ts +6 -0
- package/dist/util/DownloadUtil.js +25 -0
- package/dist/util/DownloadUtil.js.map +1 -0
- package/dist/util/EnumUtil.d.ts +19 -0
- package/dist/util/EnumUtil.js +32 -0
- package/dist/util/EnumUtil.js.map +1 -0
- package/dist/util/FormUtil.d.ts +8 -0
- package/dist/util/FormUtil.js +14 -0
- package/dist/util/FormUtil.js.map +1 -0
- package/dist/util/HtmlUtil.d.ts +8 -0
- package/dist/util/HtmlUtil.js +23 -0
- package/dist/util/HtmlUtil.js.map +1 -0
- package/dist/util/Notifications.d.ts +30 -0
- package/dist/util/Notifications.js +59 -0
- package/dist/util/Notifications.js.map +1 -0
- package/dist/util/NumberUtil.d.ts +19 -0
- package/dist/util/NumberUtil.js +33 -0
- package/dist/util/NumberUtil.js.map +1 -0
- package/dist/util/ObjectUtil.d.ts +22 -0
- package/dist/util/ObjectUtil.js +34 -0
- package/dist/util/ObjectUtil.js.map +1 -0
- package/dist/util/SearchParamsUtil.d.ts +23 -0
- package/dist/util/SearchParamsUtil.js +29 -0
- package/dist/util/SearchParamsUtil.js.map +1 -0
- package/dist/util/TransformData.d.ts +14 -0
- package/dist/util/TransformData.js +31 -0
- package/dist/util/TransformData.js.map +1 -0
- package/dist/util/ValidationUtil.d.ts +9 -0
- package/dist/util/ValidationUtil.js +16 -0
- package/dist/util/ValidationUtil.js.map +1 -0
- package/dist/util/parseActionsPageParams.d.ts +14 -0
- package/dist/util/parseActionsPageParams.js +29 -0
- package/dist/util/parseActionsPageParams.js.map +1 -0
- package/package.json +149 -5
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKitConfig } from "../../../provider/useKit.js";
|
|
3
|
+
import { formatValues } from "../../../util/TransformData.js";
|
|
4
|
+
import { errorMessage, showErrorNotification, showSuccessNotification } from "../../../util/Notifications.js";
|
|
5
|
+
import PaperCard from "../../molecule/PaperCard/PaperCard.js";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { Box, Button, Grid, Group, Stack, Text } from "@mantine/core";
|
|
9
|
+
import { IconArrowBack, IconDeviceFloppy } from "@tabler/icons-react";
|
|
10
|
+
import { modals } from "@mantine/modals";
|
|
11
|
+
// src/component/organism/DataForm/DataForm.tsx
|
|
12
|
+
/**
|
|
13
|
+
* Form in a card, with the back and submit buttons. On submit, calls `fetchMethod` (optionally after a confirmation),
|
|
14
|
+
* shows a notification and goes back to `backRoute`, if given.
|
|
15
|
+
*/
|
|
16
|
+
function DataForm(props) {
|
|
17
|
+
const { title, backRoute, fetchMethod, form, children, submit } = props;
|
|
18
|
+
const { router, messages } = useKitConfig();
|
|
19
|
+
const navigate = router.useNavigate();
|
|
20
|
+
const { Link } = router;
|
|
21
|
+
const [loading, setLoading] = useState(false);
|
|
22
|
+
const handleSubmit = async (data, evt) => {
|
|
23
|
+
setLoading(true);
|
|
24
|
+
try {
|
|
25
|
+
const effectiveData = formatValues(data);
|
|
26
|
+
await fetchMethod(effectiveData);
|
|
27
|
+
submit.successMsg && showSuccessNotification(submit.successMsg, messages.common.success);
|
|
28
|
+
backRoute && navigate(backRoute);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
showErrorNotification(error, `${submit.errorMsg}: ${errorMessage(error)}`, messages.common.error);
|
|
31
|
+
} finally {
|
|
32
|
+
setLoading(false);
|
|
33
|
+
}
|
|
34
|
+
!backRoute && evt?.preventDefault();
|
|
35
|
+
};
|
|
36
|
+
const openModal = async () => modals.openConfirmModal({
|
|
37
|
+
title: messages.form.confirmTitle,
|
|
38
|
+
centered: true,
|
|
39
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
40
|
+
size: "sm",
|
|
41
|
+
children: submit.confirmationMessage
|
|
42
|
+
}),
|
|
43
|
+
labels: {
|
|
44
|
+
confirm: messages.common.confirm,
|
|
45
|
+
cancel: messages.common.cancel
|
|
46
|
+
},
|
|
47
|
+
onConfirm: async () => await handleSubmit(form.values, void 0)
|
|
48
|
+
});
|
|
49
|
+
return /* @__PURE__ */ jsx(Grid, { children: /* @__PURE__ */ jsx(Grid.Col, {
|
|
50
|
+
span: {
|
|
51
|
+
base: 12,
|
|
52
|
+
lg: 12
|
|
53
|
+
},
|
|
54
|
+
children: /* @__PURE__ */ jsx(PaperCard, { children: /* @__PURE__ */ jsx(Box, {
|
|
55
|
+
component: "form",
|
|
56
|
+
onSubmit: form.onSubmit(submit.confirmationMessage ? openModal : handleSubmit),
|
|
57
|
+
children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
58
|
+
/* @__PURE__ */ jsx(Text, {
|
|
59
|
+
size: "lg",
|
|
60
|
+
fw: 600,
|
|
61
|
+
children: title
|
|
62
|
+
}),
|
|
63
|
+
children,
|
|
64
|
+
/* @__PURE__ */ jsxs(Group, { children: [backRoute && /* @__PURE__ */ jsx(Button, {
|
|
65
|
+
leftSection: /* @__PURE__ */ jsx(IconArrowBack, { size: 16 }),
|
|
66
|
+
component: Link,
|
|
67
|
+
href: backRoute,
|
|
68
|
+
variant: "default",
|
|
69
|
+
children: messages.common.back
|
|
70
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
71
|
+
type: "submit",
|
|
72
|
+
leftSection: /* @__PURE__ */ jsx(IconDeviceFloppy, { size: 16 }),
|
|
73
|
+
loading,
|
|
74
|
+
disabled: submit.disabled,
|
|
75
|
+
children: submit.title
|
|
76
|
+
})] })
|
|
77
|
+
] })
|
|
78
|
+
}) })
|
|
79
|
+
}) });
|
|
80
|
+
}
|
|
81
|
+
export { DataForm as default };
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=DataForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataForm.js","names":[],"sources":["../../../../src/component/organism/DataForm/DataForm.tsx"],"sourcesContent":["import React, { FormEvent, ReactElement, useState } from 'react';\n\nimport { Box, Button, Grid, Group, Stack, Text } from '@mantine/core';\nimport type { UseFormReturnType } from '@mantine/form';\nimport { modals } from '@mantine/modals';\nimport { IconArrowBack, IconDeviceFloppy } from '@tabler/icons-react';\n\nimport { useKitConfig } from '../../../provider/useKit';\nimport { formatValues } from '../../../util/TransformData';\nimport { errorMessage, showErrorNotification, showSuccessNotification } from '../../../util/Notifications';\nimport PaperCard from '../../molecule/PaperCard/PaperCard';\n\n/** Props of the submit button. */\ninterface SubmitProps {\n title: string;\n successMsg?: string;\n errorMsg: string;\n disabled?: boolean;\n\n /** Question shown in a confirmation dialog before submitting; absent to submit right away. */\n confirmationMessage?: string;\n}\n\ninterface FormProps<D extends object> {\n title: string;\n\n /** Page opened after the data is saved and by the back button; absent for no back button nor navigation. */\n backRoute?: string;\n\n /** Sends the form data (e.g. to the API). */\n fetchMethod: (data: D) => Promise<unknown>;\n form: UseFormReturnType<D>;\n submit: SubmitProps;\n}\n\n/**\n * Form in a card, with the back and submit buttons. On submit, calls `fetchMethod` (optionally after a confirmation),\n * shows a notification and goes back to `backRoute`, if given.\n */\nfunction DataForm<D extends object>(props: React.PropsWithChildren<FormProps<D>>): ReactElement {\n const { title, backRoute, fetchMethod, form, children, submit } = props;\n const { router, messages } = useKitConfig();\n const navigate = router.useNavigate();\n const { Link } = router;\n\n const [loading, setLoading] = useState(false);\n\n const handleSubmit = async (data: D, evt: FormEvent<HTMLFormElement> | undefined) => {\n setLoading(true);\n try {\n const effectiveData = formatValues(data) as D;\n await fetchMethod(effectiveData);\n submit.successMsg && showSuccessNotification(submit.successMsg, messages.common.success);\n\n backRoute && navigate(backRoute);\n } catch (error) {\n showErrorNotification(error, `${submit.errorMsg}: ${errorMessage(error)}`, messages.common.error);\n } finally {\n setLoading(false);\n }\n\n !backRoute && evt?.preventDefault();\n };\n\n const openModal = async () =>\n modals.openConfirmModal({\n title: messages.form.confirmTitle,\n centered: true,\n children: <Text size=\"sm\">{submit.confirmationMessage}</Text>,\n labels: { confirm: messages.common.confirm, cancel: messages.common.cancel },\n onConfirm: async () => await handleSubmit(form.values, undefined)\n });\n\n return (\n <Grid>\n <Grid.Col span={{ base: 12, lg: 12 }}>\n <PaperCard>\n <Box\n component=\"form\"\n onSubmit={form.onSubmit(submit.confirmationMessage ? openModal : handleSubmit)}\n >\n <Stack>\n <Text size=\"lg\" fw={600}>\n {title}\n </Text>\n\n {children}\n\n <Group>\n {backRoute && (\n <Button\n leftSection={<IconArrowBack size={16} />}\n component={Link}\n href={backRoute}\n variant=\"default\"\n >\n {messages.common.back}\n </Button>\n )}\n <Button\n type=\"submit\"\n leftSection={<IconDeviceFloppy size={16} />}\n loading={loading}\n disabled={submit.disabled}\n >\n {submit.title}\n </Button>\n </Group>\n </Stack>\n </Box>\n </PaperCard>\n </Grid.Col>\n </Grid>\n );\n}\n\nexport default DataForm;\n"],"mappings":";;;;;;;;;;;;;;;AAuCA,SAAS,SAA2B,OAA4D;CAC5F,MAAM,EAAE,OAAO,WAAW,aAAa,MAAM,UAAU,WAAW;CAClE,MAAM,EAAE,QAAQ,aAAa,aAAa;CAC1C,MAAM,WAAW,OAAO,YAAY;CACpC,MAAM,EAAE,SAAS;CAEjB,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAE5C,MAAM,eAAe,OAAO,MAAS,QAAgD;EACjF,WAAW,IAAI;EACf,IAAI;GACA,MAAM,gBAAgB,aAAa,IAAI;GACvC,MAAM,YAAY,aAAa;GAC/B,OAAO,cAAc,wBAAwB,OAAO,YAAY,SAAS,OAAO,OAAO;GAEvF,aAAa,SAAS,SAAS;EACnC,SAAS,OAAO;GACZ,sBAAsB,OAAO,GAAG,OAAO,SAAS,IAAI,aAAa,KAAK,KAAK,SAAS,OAAO,KAAK;EACpG,UAAU;GACN,WAAW,KAAK;EACpB;EAEA,CAAC,aAAa,KAAK,eAAe;CACtC;CAEA,MAAM,YAAY,YACd,OAAO,iBAAiB;EACpB,OAAO,SAAS,KAAK;EACrB,UAAU;EACV,UAAU,oBAAC,MAAD;GAAM,MAAK;GAAM,UAAA,OAAO;EAA0B,CAAA;EAC5D,QAAQ;GAAE,SAAS,SAAS,OAAO;GAAS,QAAQ,SAAS,OAAO;EAAO;EAC3E,WAAW,YAAY,MAAM,aAAa,KAAK,QAAQ,KAAA,CAAS;CACpE,CAAC;CAEL,OACI,oBAAC,MAAD,EAAA,UACI,oBAAC,KAAK,KAAN;EAAU,MAAM;GAAE,MAAM;GAAI,IAAI;EAAG;EAC/B,UAAA,oBAAC,WAAD,EAAA,UACI,oBAAC,KAAD;GACI,WAAU;GACV,UAAU,KAAK,SAAS,OAAO,sBAAsB,YAAY,YAAY;GAE7E,UAAA,qBAAC,OAAD,EAAA,UAAA;IACI,oBAAC,MAAD;KAAM,MAAK;KAAK,IAAI;KACf,UAAA;IACC,CAAA;IAEL;IAED,qBAAC,OAAD,EAAA,UAAA,CACK,aACG,oBAAC,QAAD;KACI,aAAa,oBAAC,eAAD,EAAe,MAAM,GAAK,CAAA;KACvC,WAAW;KACX,MAAM;KACN,SAAQ;KAEP,UAAA,SAAS,OAAO;IACb,CAAA,GAEZ,oBAAC,QAAD;KACI,MAAK;KACL,aAAa,oBAAC,kBAAD,EAAkB,MAAM,GAAK,CAAA;KACjC;KACT,UAAU,OAAO;KAEhB,UAAA,OAAO;IACJ,CAAA,CACL,EAAA,CAAA;GACJ,EAAA,CAAA;EACN,CAAA,EACE,CAAA;CACL,CAAA,EACR,CAAA;AAEd"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { Identifiable } from '../../../model/Identifiable';
|
|
3
|
+
type TabListProps<M extends Identifiable> = {
|
|
4
|
+
/** One tab per object. */
|
|
5
|
+
dataArray: M[];
|
|
6
|
+
/** Returns the icon of the tab of an object; without it, all tabs use a generic icon. */
|
|
7
|
+
tabIconFn?: (obj: M, tabIndex: number) => ReactNode;
|
|
8
|
+
/** Index of the tab selected at first. */
|
|
9
|
+
defaultTabIndex?: number;
|
|
10
|
+
/** Value of the selected tab, to control it from outside (the id of the object, as a string). */
|
|
11
|
+
value?: string | null;
|
|
12
|
+
onChange?: (value: string | null) => void;
|
|
13
|
+
/** Returns the title of the tab of an object. */
|
|
14
|
+
tabTitleFn: (obj: M) => string;
|
|
15
|
+
/** Returns the content of the tab of an object. */
|
|
16
|
+
children: (obj: M, tabIndex: number) => ReactNode;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Tabs built from an array of objects, one tab per object.
|
|
20
|
+
* Each tab is as wide as its title (up to a maximum width, wrapping longer titles), and tabs that do not fit in a row
|
|
21
|
+
* move to the next one, aligned to the left, keeping the same look.
|
|
22
|
+
*/
|
|
23
|
+
declare function DataTabList<M extends Identifiable>({ dataArray, tabIconFn, tabTitleFn, defaultTabIndex, value, onChange, children }: TabListProps<M>): ReactElement;
|
|
24
|
+
export default DataTabList;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import DataTabList_module_default from "./DataTabList.module.js";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Tabs } from "@mantine/core";
|
|
5
|
+
import { IconTableColumn } from "@tabler/icons-react";
|
|
6
|
+
// src/component/organism/DataTabList/DataTabList.tsx
|
|
7
|
+
/**
|
|
8
|
+
* Tabs built from an array of objects, one tab per object.
|
|
9
|
+
* Each tab is as wide as its title (up to a maximum width, wrapping longer titles), and tabs that do not fit in a row
|
|
10
|
+
* move to the next one, aligned to the left, keeping the same look.
|
|
11
|
+
*/
|
|
12
|
+
function DataTabList({ dataArray, tabIconFn = () => /* @__PURE__ */ jsx(IconTableColumn, {}), tabTitleFn, defaultTabIndex = 0, value, onChange, children }) {
|
|
13
|
+
if (dataArray.length == 0) return /* @__PURE__ */ jsx(Fragment, {});
|
|
14
|
+
const tabValue = (obj, index) => (obj.id || index).toString();
|
|
15
|
+
return /* @__PURE__ */ jsxs(Tabs, {
|
|
16
|
+
defaultValue: dataArray[defaultTabIndex]?.id?.toString(),
|
|
17
|
+
value,
|
|
18
|
+
onChange,
|
|
19
|
+
variant: "pills",
|
|
20
|
+
classNames: {
|
|
21
|
+
tab: DataTabList_module_default.tab,
|
|
22
|
+
tabSection: DataTabList_module_default.tabSection,
|
|
23
|
+
panel: DataTabList_module_default.panel
|
|
24
|
+
},
|
|
25
|
+
children: [/* @__PURE__ */ jsx(Tabs.List, { children: dataArray.map((data, i) => /* @__PURE__ */ jsx(Tabs.Tab, {
|
|
26
|
+
value: tabValue(data, i),
|
|
27
|
+
leftSection: tabIconFn(data, i),
|
|
28
|
+
children: tabTitleFn(data)
|
|
29
|
+
}, tabValue(data, i))) }), dataArray.map((data, i) => /* @__PURE__ */ jsx(Tabs.Panel, {
|
|
30
|
+
value: tabValue(data, i),
|
|
31
|
+
children: children(data, i)
|
|
32
|
+
}, tabValue(data, i)))]
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export { DataTabList as default };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=DataTabList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTabList.js","names":["_Fragment","classes"],"sources":["../../../../src/component/organism/DataTabList/DataTabList.tsx"],"sourcesContent":["import { Tabs } from '@mantine/core';\nimport { IconTableColumn } from '@tabler/icons-react';\nimport { ReactElement, ReactNode } from 'react';\n\nimport type { Identifiable } from '../../../model/Identifiable';\nimport classes from './DataTabList.module.css';\n\ntype TabListProps<M extends Identifiable> = {\n /** One tab per object. */\n dataArray: M[];\n\n /** Returns the icon of the tab of an object; without it, all tabs use a generic icon. */\n tabIconFn?: (obj: M, tabIndex: number) => ReactNode;\n\n /** Index of the tab selected at first. */\n defaultTabIndex?: number;\n\n /** Value of the selected tab, to control it from outside (the id of the object, as a string). */\n value?: string | null;\n onChange?: (value: string | null) => void;\n\n /** Returns the title of the tab of an object. */\n tabTitleFn: (obj: M) => string;\n\n /** Returns the content of the tab of an object. */\n children: (obj: M, tabIndex: number) => ReactNode;\n};\n\n/**\n * Tabs built from an array of objects, one tab per object.\n * Each tab is as wide as its title (up to a maximum width, wrapping longer titles), and tabs that do not fit in a row\n * move to the next one, aligned to the left, keeping the same look.\n */\nfunction DataTabList<M extends Identifiable>({\n dataArray,\n tabIconFn = () => <IconTableColumn />,\n tabTitleFn,\n defaultTabIndex = 0,\n value,\n onChange,\n children\n}: TabListProps<M>): ReactElement {\n if (dataArray.length == 0) {\n return <></>;\n }\n\n const tabValue = (obj: M, index: number) => (obj.id || index).toString();\n\n return (\n <Tabs\n defaultValue={dataArray[defaultTabIndex]?.id?.toString()}\n value={value}\n onChange={onChange}\n variant=\"pills\"\n classNames={{ tab: classes.tab, tabSection: classes.tabSection, panel: classes.panel }}\n >\n <Tabs.List>\n {dataArray.map((data, i) => (\n <Tabs.Tab value={tabValue(data, i)} key={tabValue(data, i)} leftSection={tabIconFn(data, i)}>\n {tabTitleFn(data)}\n </Tabs.Tab>\n ))}\n </Tabs.List>\n\n {dataArray.map((data, i) => (\n <Tabs.Panel value={tabValue(data, i)} key={tabValue(data, i)}>\n {children(data, i)}\n </Tabs.Panel>\n ))}\n </Tabs>\n );\n}\n\nexport default DataTabList;\n"],"mappings":";;;;;;;;;;;AAiCA,SAAS,YAAoC,EACzC,WACA,kBAAkB,oBAAC,iBAAD,CAAkB,CAAA,GACpC,YACA,kBAAkB,GAClB,OACA,UACA,YAC8B;CAC9B,IAAI,UAAU,UAAU,GACpB,OAAO,oBAAAA,UAAA,CAAI,CAAA;CAGf,MAAM,YAAY,KAAQ,WAAmB,IAAI,MAAM,MAAA,CAAO,SAAS;CAEvE,OACI,qBAAC,MAAD;EACI,cAAc,UAAU,gBAAgB,EAAE,IAAI,SAAS;EAChD;EACG;EACV,SAAQ;EACR,YAAY;GAAE,KAAKC,2BAAQ;GAAK,YAAYA,2BAAQ;GAAY,OAAOA,2BAAQ;EAAM;EALzF,UAAA,CAOI,oBAAC,KAAK,MAAN,EAAA,UACK,UAAU,KAAK,MAAM,MAClB,oBAAC,KAAK,KAAN;GAAU,OAAO,SAAS,MAAM,CAAC;GAA2B,aAAa,UAAU,MAAM,CAAC;GACrF,UAAA,WAAW,IAAI;EACV,GAF+B,SAAS,MAAM,CAAC,CAE/C,CACb,EACM,CAAA,GAEV,UAAU,KAAK,MAAM,MAClB,oBAAC,KAAK,OAAN;GAAY,OAAO,SAAS,MAAM,CAAC;GAC9B,UAAA,SAAS,MAAM,CAAC;EACT,GAF+B,SAAS,MAAM,CAAC,CAE/C,CACf,CACC;;AAEd"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// src/component/organism/DataTabList/DataTabList.module.css
|
|
3
|
+
var tab = "mk-DataTabList-module-tab-15vyU";
|
|
4
|
+
var tabSection = "mk-DataTabList-module-tabSection-WA0SY";
|
|
5
|
+
var panel = "mk-DataTabList-module-panel-R37nf";
|
|
6
|
+
var DataTabList_module_default = {
|
|
7
|
+
tab,
|
|
8
|
+
tabSection,
|
|
9
|
+
panel
|
|
10
|
+
};
|
|
11
|
+
export { DataTabList_module_default as default, panel, tab, tabSection };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=DataTabList.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTabList.module.js","names":[],"sources":["../../../../src/component/organism/DataTabList/DataTabList.module.css"],"sourcesContent":["/*\n * Tabs as wide as their own text (without stretching to fill the row), up to a maximum width.\n * A title longer than the limit wraps in more than one line inside the tab, instead of widening it.\n */\n.tab {\n max-width: 14rem;\n min-height: 2.5rem;\n white-space: normal;\n line-height: 1.25;\n\n /* Border on the inactive tabs, so they look clickable, and not like loose text of the page. */\n border: 1px solid var(--mantine-color-default-border);\n}\n\n.tab[data-active] {\n border-color: var(--mantine-primary-color-filled);\n}\n\n/* Same size for any given icon, so all tabs have the same height. */\n.tabSection svg {\n width: 1rem;\n height: 1rem;\n}\n\n.panel {\n padding-top: var(--mantine-spacing-xs);\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { CSSProperties, ReactElement } from 'react';
|
|
2
|
+
import type { EChartsOption } from 'echarts';
|
|
3
|
+
import { EChartDataAccessors } from './buildEChartOption';
|
|
4
|
+
import { EChartEventHandlers, EChartMaps, EChartRenderer } from './useEChart';
|
|
5
|
+
/**
|
|
6
|
+
* Props of the {@link EChart}. `getName` and `getValue` extract from each item of `data` the name and the value of the
|
|
7
|
+
* element in the chart.
|
|
8
|
+
*/
|
|
9
|
+
export type EChartProps<T> = EChartDataAccessors<T> & {
|
|
10
|
+
/** Raw domain data, used to fill the `data` of the series that define no data of their own. */
|
|
11
|
+
data: T[];
|
|
12
|
+
/**
|
|
13
|
+
* ECharts options specific to the chart (series type, map, axes etc.).
|
|
14
|
+
* They replace the default values of `tooltip`, `toolbox` and `visualMap` (deep merge).
|
|
15
|
+
*/
|
|
16
|
+
option?: EChartsOption;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the elements of the chart should be colored according to their percentage value (0..1), showing a
|
|
19
|
+
* gradient legend from "0%" to "100%" (see {@link DEFAULT_VISUAL_MAP}). Default: `true`.
|
|
20
|
+
* Turn it off in charts of absolute values (money, volumes), since the 0..1 scale does not match these values and
|
|
21
|
+
* the color of the series would be replaced by the one of the scale.
|
|
22
|
+
*/
|
|
23
|
+
withVisualMap?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Functions that handle ECharts events, indexed by the event name (e.g. `click`, `legendselectchanged`).
|
|
26
|
+
* Prefer a stable object (e.g. with `useMemo`), since the handlers are bound again when the object changes.
|
|
27
|
+
*/
|
|
28
|
+
onEvents?: EChartEventHandlers;
|
|
29
|
+
/**
|
|
30
|
+
* Maps (e.g. the GeoJSON of the cities) used by the `map` series, indexed by the name used in `series[i].map`.
|
|
31
|
+
* They are registered before the chart is created and again when the object changes, so prefer a stable object
|
|
32
|
+
* (e.g. with `useMemo`).
|
|
33
|
+
*/
|
|
34
|
+
maps?: EChartMaps;
|
|
35
|
+
/** How the chart is drawn: `svg` is printed as vector graphics (e.g. in reports). Default: `canvas`. */
|
|
36
|
+
renderer?: EChartRenderer;
|
|
37
|
+
/** Style of the chart container. Default: {@link DEFAULT_STYLE}. */
|
|
38
|
+
style?: CSSProperties;
|
|
39
|
+
className?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* React wrapper of Apache ECharts that receives the raw domain data and builds the series from it, applying the
|
|
43
|
+
* default `option` values.
|
|
44
|
+
* The chart is redrawn when a prop changes, so prefer giving stable `option`, `getName` and `getValue` (e.g. with
|
|
45
|
+
* `useMemo`/`useCallback` or defined outside the component) to avoid needless redraws.
|
|
46
|
+
*/
|
|
47
|
+
export declare function EChart<T>({ data, getName, getValue, option, withVisualMap, onEvents, maps, renderer, style, className }: EChartProps<T>): ReactElement;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKitMessages } from "../../../provider/useKit.js";
|
|
3
|
+
import { buildEChartOption } from "./buildEChartOption.js";
|
|
4
|
+
import { DEFAULT_STYLE } from "./echartDefaults.js";
|
|
5
|
+
import { useEChart } from "./useEChart.js";
|
|
6
|
+
import { useMemo } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
// src/component/organism/EChart/EChart.tsx
|
|
9
|
+
/**
|
|
10
|
+
* React wrapper of Apache ECharts that receives the raw domain data and builds the series from it, applying the
|
|
11
|
+
* default `option` values.
|
|
12
|
+
* The chart is redrawn when a prop changes, so prefer giving stable `option`, `getName` and `getValue` (e.g. with
|
|
13
|
+
* `useMemo`/`useCallback` or defined outside the component) to avoid needless redraws.
|
|
14
|
+
*/
|
|
15
|
+
function EChart({ data, getName, getValue, option, withVisualMap = true, onEvents, maps, renderer, style = DEFAULT_STYLE, className }) {
|
|
16
|
+
const saveAsImageTitle = useKitMessages().chart.saveAsImage;
|
|
17
|
+
const finalOption = useMemo(() => buildEChartOption(data, {
|
|
18
|
+
getName,
|
|
19
|
+
getValue
|
|
20
|
+
}, option, withVisualMap, saveAsImageTitle), [
|
|
21
|
+
data,
|
|
22
|
+
getName,
|
|
23
|
+
getValue,
|
|
24
|
+
option,
|
|
25
|
+
withVisualMap,
|
|
26
|
+
saveAsImageTitle
|
|
27
|
+
]);
|
|
28
|
+
const containerRef = useEChart(finalOption, onEvents, maps, renderer);
|
|
29
|
+
return /* @__PURE__ */ jsx("div", {
|
|
30
|
+
ref: containerRef,
|
|
31
|
+
style,
|
|
32
|
+
className
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export { EChart };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=EChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EChart.js","names":[],"sources":["../../../../src/component/organism/EChart/EChart.tsx"],"sourcesContent":["'use client';\n\nimport { CSSProperties, ReactElement, useMemo } from 'react';\n\nimport type { EChartsOption } from 'echarts';\n\nimport { useKitMessages } from '../../../provider/useKit';\nimport { buildEChartOption, EChartDataAccessors } from './buildEChartOption';\nimport { DEFAULT_STYLE } from './echartDefaults';\nimport { EChartEventHandlers, EChartMaps, EChartRenderer, useEChart } from './useEChart';\n\n/**\n * Props of the {@link EChart}. `getName` and `getValue` extract from each item of `data` the name and the value of the\n * element in the chart.\n */\nexport type EChartProps<T> = EChartDataAccessors<T> & {\n /** Raw domain data, used to fill the `data` of the series that define no data of their own. */\n data: T[];\n\n /**\n * ECharts options specific to the chart (series type, map, axes etc.).\n * They replace the default values of `tooltip`, `toolbox` and `visualMap` (deep merge).\n */\n option?: EChartsOption;\n\n /**\n * Whether the elements of the chart should be colored according to their percentage value (0..1), showing a\n * gradient legend from \"0%\" to \"100%\" (see {@link DEFAULT_VISUAL_MAP}). Default: `true`.\n * Turn it off in charts of absolute values (money, volumes), since the 0..1 scale does not match these values and\n * the color of the series would be replaced by the one of the scale.\n */\n withVisualMap?: boolean;\n\n /**\n * Functions that handle ECharts events, indexed by the event name (e.g. `click`, `legendselectchanged`).\n * Prefer a stable object (e.g. with `useMemo`), since the handlers are bound again when the object changes.\n */\n onEvents?: EChartEventHandlers;\n\n /**\n * Maps (e.g. the GeoJSON of the cities) used by the `map` series, indexed by the name used in `series[i].map`.\n * They are registered before the chart is created and again when the object changes, so prefer a stable object\n * (e.g. with `useMemo`).\n */\n maps?: EChartMaps;\n\n /** How the chart is drawn: `svg` is printed as vector graphics (e.g. in reports). Default: `canvas`. */\n renderer?: EChartRenderer;\n\n /** Style of the chart container. Default: {@link DEFAULT_STYLE}. */\n style?: CSSProperties;\n\n className?: string;\n};\n\n/**\n * React wrapper of Apache ECharts that receives the raw domain data and builds the series from it, applying the\n * default `option` values.\n * The chart is redrawn when a prop changes, so prefer giving stable `option`, `getName` and `getValue` (e.g. with\n * `useMemo`/`useCallback` or defined outside the component) to avoid needless redraws.\n */\nexport function EChart<T>({\n data,\n getName,\n getValue,\n option,\n withVisualMap = true,\n onEvents,\n maps,\n renderer,\n style = DEFAULT_STYLE,\n className\n}: EChartProps<T>): ReactElement {\n const saveAsImageTitle = useKitMessages().chart.saveAsImage;\n const finalOption = useMemo(\n () => buildEChartOption(data, { getName, getValue }, option, withVisualMap, saveAsImageTitle),\n [data, getName, getValue, option, withVisualMap, saveAsImageTitle]\n );\n const containerRef = useEChart(finalOption, onEvents, maps, renderer);\n\n return <div ref={containerRef} style={style} className={className} />;\n}\n"],"mappings":";;;;;;;;;;;;;;AA6DA,SAAgB,OAAU,EACtB,MACA,SACA,UACA,QACA,gBAAgB,MAChB,UACA,MACA,UACA,QAAQ,eACR,aAC6B;CAC7B,MAAM,mBAAmB,eAAe,CAAC,CAAC,MAAM;CAChD,MAAM,cAAc,cACV,kBAAkB,MAAM;EAAE;EAAS;CAAS,GAAG,QAAQ,eAAe,gBAAgB,GAC5F;EAAC;EAAM;EAAS;EAAU;EAAQ;EAAe;CAAgB,CACrE;CACA,MAAM,eAAe,UAAU,aAAa,UAAU,MAAM,QAAQ;CAEpE,OAAO,oBAAC,OAAD;EAAK,KAAK;EAAqB;EAAkB;CAAY,CAAA;AACxE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { EChartsOption } from 'echarts';
|
|
2
|
+
/**
|
|
3
|
+
* Value of an element of the chart. `null`/`undefined` mean an absent value, which ECharts shows as empty (e.g. a
|
|
4
|
+
* city without a computed index).
|
|
5
|
+
*/
|
|
6
|
+
export type EChartValue = number | null | undefined;
|
|
7
|
+
/** Element of a series, in the format ECharts expects in `series[i].data`. */
|
|
8
|
+
export type EChartDataItem = {
|
|
9
|
+
name: string;
|
|
10
|
+
value: EChartValue;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Functions that extract from a domain item what ECharts needs to show it.
|
|
14
|
+
* They are used by the {@link EChart}, so whoever uses it gives the raw data, without building the series by hand.
|
|
15
|
+
*/
|
|
16
|
+
export type EChartDataAccessors<T> = {
|
|
17
|
+
/** Returns the name of the element in the chart (e.g. the code of a city, which links the data to the map area). */
|
|
18
|
+
getName: (item: T) => string;
|
|
19
|
+
/** Returns the value of the element in the chart. */
|
|
20
|
+
getValue: (item: T) => EChartValue;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Converts the domain data to the `{ name, value }[]` format used in the ECharts series.
|
|
24
|
+
* @param data raw domain data
|
|
25
|
+
* @param accessors functions that extract the name and the value of each item
|
|
26
|
+
* @return an element `{ name, value }` for each item of `data`, in the same order
|
|
27
|
+
*/
|
|
28
|
+
export declare function toEChartData<T>(data: T[], { getName, getValue }: EChartDataAccessors<T>): EChartDataItem[];
|
|
29
|
+
/**
|
|
30
|
+
* Builds the final `option` of a chart, applying the default values and the domain data.
|
|
31
|
+
* The attributes of `option` replace the corresponding defaults (deep merge).
|
|
32
|
+
* @param data raw domain data
|
|
33
|
+
* @param accessors functions that extract the name and the value of each item
|
|
34
|
+
* @param option options specific to the chart
|
|
35
|
+
* @param withVisualMap whether the elements should be colored according to their percentage value (0..1), with the
|
|
36
|
+
* gradient legend of the {@link DEFAULT_VISUAL_MAP}. Use `false` in charts of absolute values.
|
|
37
|
+
* @param saveAsImageTitle title of the button that saves the chart as an image, in the language of the user
|
|
38
|
+
* @return the `option` ready to be given to the ECharts `setOption`
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildEChartOption<T>(data: T[], accessors: EChartDataAccessors<T>, option?: EChartsOption, withVisualMap?: boolean, saveAsImageTitle?: string): EChartsOption;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DEFAULT_OPTION, DEFAULT_VISUAL_MAP } from "./echartDefaults.js";
|
|
3
|
+
import { mergeDeep } from "../../../util/ObjectUtil.js";
|
|
4
|
+
// src/component/organism/EChart/buildEChartOption.ts
|
|
5
|
+
/**
|
|
6
|
+
* Converts the domain data to the `{ name, value }[]` format used in the ECharts series.
|
|
7
|
+
* @param data raw domain data
|
|
8
|
+
* @param accessors functions that extract the name and the value of each item
|
|
9
|
+
* @return an element `{ name, value }` for each item of `data`, in the same order
|
|
10
|
+
*/
|
|
11
|
+
function toEChartData(data, { getName, getValue }) {
|
|
12
|
+
return data.map((item) => ({
|
|
13
|
+
name: getName(item),
|
|
14
|
+
value: getValue(item)
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Fills the `data` of the series that define no data of their own. Series that already have `data` are kept as they are.
|
|
19
|
+
* @param series single series or array of series, as accepted by the ECharts `option.series`
|
|
20
|
+
* @param chartData data to use in the series
|
|
21
|
+
* @return the series in the same format received (single object or array), or `undefined` if there are no series
|
|
22
|
+
*/
|
|
23
|
+
function fillSeriesData(series, chartData) {
|
|
24
|
+
const fill = (serie) => "data" in serie && serie.data !== void 0 ? serie : {
|
|
25
|
+
...serie,
|
|
26
|
+
data: chartData
|
|
27
|
+
};
|
|
28
|
+
if (series === void 0) return void 0;
|
|
29
|
+
return Array.isArray(series) ? series.map(fill) : fill(series);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Builds the final `option` of a chart, applying the default values and the domain data.
|
|
33
|
+
* The attributes of `option` replace the corresponding defaults (deep merge).
|
|
34
|
+
* @param data raw domain data
|
|
35
|
+
* @param accessors functions that extract the name and the value of each item
|
|
36
|
+
* @param option options specific to the chart
|
|
37
|
+
* @param withVisualMap whether the elements should be colored according to their percentage value (0..1), with the
|
|
38
|
+
* gradient legend of the {@link DEFAULT_VISUAL_MAP}. Use `false` in charts of absolute values.
|
|
39
|
+
* @param saveAsImageTitle title of the button that saves the chart as an image, in the language of the user
|
|
40
|
+
* @return the `option` ready to be given to the ECharts `setOption`
|
|
41
|
+
*/
|
|
42
|
+
function buildEChartOption(data, accessors, option = {}, withVisualMap = true, saveAsImageTitle) {
|
|
43
|
+
const defaultOption = saveAsImageTitle ? mergeDeep(DEFAULT_OPTION, { toolbox: { feature: { saveAsImage: { title: saveAsImageTitle } } } }) : DEFAULT_OPTION;
|
|
44
|
+
const defaults = withVisualMap ? {
|
|
45
|
+
...defaultOption,
|
|
46
|
+
visualMap: DEFAULT_VISUAL_MAP
|
|
47
|
+
} : defaultOption;
|
|
48
|
+
const mergedOption = mergeDeep(defaults, option);
|
|
49
|
+
const series = fillSeriesData(mergedOption.series, toEChartData(data, accessors));
|
|
50
|
+
return series === void 0 ? mergedOption : {
|
|
51
|
+
...mergedOption,
|
|
52
|
+
series
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export { buildEChartOption, toEChartData };
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=buildEChartOption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildEChartOption.js","names":[],"sources":["../../../../src/component/organism/EChart/buildEChartOption.ts"],"sourcesContent":["import type { EChartsOption, SeriesOption } from 'echarts';\n\nimport { DEFAULT_OPTION, DEFAULT_VISUAL_MAP } from './echartDefaults';\nimport { mergeDeep } from '../../../util/ObjectUtil';\n\n/**\n * Value of an element of the chart. `null`/`undefined` mean an absent value, which ECharts shows as empty (e.g. a\n * city without a computed index).\n */\nexport type EChartValue = number | null | undefined;\n\n/** Element of a series, in the format ECharts expects in `series[i].data`. */\nexport type EChartDataItem = { name: string; value: EChartValue };\n\n/**\n * Functions that extract from a domain item what ECharts needs to show it.\n * They are used by the {@link EChart}, so whoever uses it gives the raw data, without building the series by hand.\n */\nexport type EChartDataAccessors<T> = {\n /** Returns the name of the element in the chart (e.g. the code of a city, which links the data to the map area). */\n getName: (item: T) => string;\n\n /** Returns the value of the element in the chart. */\n getValue: (item: T) => EChartValue;\n};\n\n/**\n * Converts the domain data to the `{ name, value }[]` format used in the ECharts series.\n * @param data raw domain data\n * @param accessors functions that extract the name and the value of each item\n * @return an element `{ name, value }` for each item of `data`, in the same order\n */\nexport function toEChartData<T>(data: T[], { getName, getValue }: EChartDataAccessors<T>): EChartDataItem[] {\n return data.map(item => ({ name: getName(item), value: getValue(item) }));\n}\n\n/**\n * Fills the `data` of the series that define no data of their own. Series that already have `data` are kept as they are.\n * @param series single series or array of series, as accepted by the ECharts `option.series`\n * @param chartData data to use in the series\n * @return the series in the same format received (single object or array), or `undefined` if there are no series\n */\nfunction fillSeriesData(series: EChartsOption['series'], chartData: EChartDataItem[]): EChartsOption['series'] {\n const fill = (serie: SeriesOption): SeriesOption =>\n 'data' in serie && serie.data !== undefined ? serie : ({ ...serie, data: chartData } as SeriesOption);\n\n if (series === undefined) return undefined;\n\n return Array.isArray(series) ? series.map(fill) : fill(series);\n}\n\n/**\n * Builds the final `option` of a chart, applying the default values and the domain data.\n * The attributes of `option` replace the corresponding defaults (deep merge).\n * @param data raw domain data\n * @param accessors functions that extract the name and the value of each item\n * @param option options specific to the chart\n * @param withVisualMap whether the elements should be colored according to their percentage value (0..1), with the\n * gradient legend of the {@link DEFAULT_VISUAL_MAP}. Use `false` in charts of absolute values.\n * @param saveAsImageTitle title of the button that saves the chart as an image, in the language of the user\n * @return the `option` ready to be given to the ECharts `setOption`\n */\nexport function buildEChartOption<T>(\n data: T[],\n accessors: EChartDataAccessors<T>,\n option: EChartsOption = {},\n withVisualMap: boolean = true,\n saveAsImageTitle?: string\n): EChartsOption {\n const defaultOption: EChartsOption = saveAsImageTitle\n ? mergeDeep(DEFAULT_OPTION, { toolbox: { feature: { saveAsImage: { title: saveAsImageTitle } } } })\n : DEFAULT_OPTION;\n const defaults: EChartsOption = withVisualMap ? { ...defaultOption, visualMap: DEFAULT_VISUAL_MAP } : defaultOption;\n const mergedOption = mergeDeep(defaults, option);\n const series = fillSeriesData(mergedOption.series, toEChartData(data, accessors));\n\n /* Without series in the option, there is nowhere to put the data: returns the option as it is, without creating\n `series: undefined`. With series, returns a copy of the option whose series are the ones that received `data`. */\n return series === undefined ? mergedOption : { ...mergedOption, series };\n}\n"],"mappings":";;;;;;;;;;AAgCA,SAAgB,aAAgB,MAAW,EAAE,SAAS,YAAsD;CACxG,OAAO,KAAK,KAAI,UAAS;EAAE,MAAM,QAAQ,IAAI;EAAG,OAAO,SAAS,IAAI;CAAE,EAAE;AAC5E;;;;;;;AAQA,SAAS,eAAe,QAAiC,WAAsD;CAC3G,MAAM,QAAQ,UACV,UAAU,SAAS,MAAM,SAAS,KAAA,IAAY,QAAS;EAAE,GAAG;EAAO,MAAM;CAAU;CAEvF,IAAI,WAAW,KAAA,GAAW,OAAO,KAAA;CAEjC,OAAO,MAAM,QAAQ,MAAM,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK,MAAM;AACjE;;;;;;;;;;;;AAaA,SAAgB,kBACZ,MACA,WACA,SAAwB,CAAC,GACzB,gBAAyB,MACzB,kBACa;CACb,MAAM,gBAA+B,mBAC/B,UAAU,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,iBAAiB,EAAE,EAAE,EAAE,CAAC,IAChG;CACN,MAAM,WAA0B,gBAAgB;EAAE,GAAG;EAAe,WAAW;CAAmB,IAAI;CACtG,MAAM,eAAe,UAAU,UAAU,MAAM;CAC/C,MAAM,SAAS,eAAe,aAAa,QAAQ,aAAa,MAAM,SAAS,CAAC;CAIhF,OAAO,WAAW,KAAA,IAAY,eAAe;EAAE,GAAG;EAAc;CAAO;AAC3E"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ChartSeries } from './ChartSeries';
|
|
2
|
+
import { ChartTypeId } from './ChartTypeId';
|
|
3
|
+
import { CartesianChart, CartesianSeries, DataPoint } from './CartesianChart';
|
|
4
|
+
/** Color of the columns with a negative value (e.g. a deficit), to set them apart from the positive ones. */
|
|
5
|
+
export declare const NEGATIVE_VALUE_COLOR = "#d9480f";
|
|
6
|
+
/**
|
|
7
|
+
* Grouped column chart: compares the series category by category.
|
|
8
|
+
* Suited to flows (e.g. yearly values) and to balances that may be negative (deficit/surplus): the negative columns
|
|
9
|
+
* get the {@link NEGATIVE_VALUE_COLOR}, without changing the color of the series in the legend.
|
|
10
|
+
* @author Manoel Campos
|
|
11
|
+
*/
|
|
12
|
+
export declare class BarChart extends CartesianChart {
|
|
13
|
+
readonly id: ChartTypeId;
|
|
14
|
+
protected seriesStyle(): CartesianSeries;
|
|
15
|
+
protected seriesData(serie: ChartSeries): DataPoint[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Gives the {@link NEGATIVE_VALUE_COLOR} only to the negative values. The others keep the color of the series.
|
|
19
|
+
* @param values values of a series
|
|
20
|
+
* @return the values in the `series[i].data` format, with their own style in the negative ones
|
|
21
|
+
*/
|
|
22
|
+
export declare function highlightNegativeValues(values: (number | null)[]): DataPoint[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { CartesianChart } from "./CartesianChart.js";
|
|
3
|
+
// src/component/organism/EChart/chart/BarChart.ts
|
|
4
|
+
/** Color of the columns with a negative value (e.g. a deficit), to set them apart from the positive ones. */
|
|
5
|
+
var NEGATIVE_VALUE_COLOR = "#d9480f";
|
|
6
|
+
/**
|
|
7
|
+
* Grouped column chart: compares the series category by category.
|
|
8
|
+
* Suited to flows (e.g. yearly values) and to balances that may be negative (deficit/surplus): the negative columns
|
|
9
|
+
* get the {@link NEGATIVE_VALUE_COLOR}, without changing the color of the series in the legend.
|
|
10
|
+
* @author Manoel Campos
|
|
11
|
+
*/
|
|
12
|
+
var BarChart = class extends CartesianChart {
|
|
13
|
+
id = "bar";
|
|
14
|
+
seriesStyle() {
|
|
15
|
+
return { type: "bar" };
|
|
16
|
+
}
|
|
17
|
+
seriesData(serie) {
|
|
18
|
+
return highlightNegativeValues(serie.values);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Gives the {@link NEGATIVE_VALUE_COLOR} only to the negative values. The others keep the color of the series.
|
|
23
|
+
* @param values values of a series
|
|
24
|
+
* @return the values in the `series[i].data` format, with their own style in the negative ones
|
|
25
|
+
*/
|
|
26
|
+
function highlightNegativeValues(values) {
|
|
27
|
+
return values.map((value) => value !== null && value < 0 ? {
|
|
28
|
+
value,
|
|
29
|
+
itemStyle: { color: NEGATIVE_VALUE_COLOR }
|
|
30
|
+
} : value);
|
|
31
|
+
}
|
|
32
|
+
export { BarChart, NEGATIVE_VALUE_COLOR, highlightNegativeValues };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=BarChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BarChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/BarChart.ts"],"sourcesContent":["import { ChartSeries } from './ChartSeries';\nimport { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries, DataPoint } from './CartesianChart';\n\n/** Color of the columns with a negative value (e.g. a deficit), to set them apart from the positive ones. */\nexport const NEGATIVE_VALUE_COLOR = '#d9480f';\n\n/**\n * Grouped column chart: compares the series category by category.\n * Suited to flows (e.g. yearly values) and to balances that may be negative (deficit/surplus): the negative columns\n * get the {@link NEGATIVE_VALUE_COLOR}, without changing the color of the series in the legend.\n * @author Manoel Campos\n */\nexport class BarChart extends CartesianChart {\n readonly id: ChartTypeId = 'bar';\n\n protected seriesStyle(): CartesianSeries {\n return { type: 'bar' };\n }\n\n protected seriesData(serie: ChartSeries): DataPoint[] {\n return highlightNegativeValues(serie.values);\n }\n}\n\n/**\n * Gives the {@link NEGATIVE_VALUE_COLOR} only to the negative values. The others keep the color of the series.\n * @param values values of a series\n * @return the values in the `series[i].data` format, with their own style in the negative ones\n */\nexport function highlightNegativeValues(values: (number | null)[]): DataPoint[] {\n return values.map(value =>\n value !== null && value < 0 ? { value, itemStyle: { color: NEGATIVE_VALUE_COLOR } } : value\n );\n}\n"],"mappings":";;;;AAKA,IAAa,uBAAuB;;;;;;;AAQpC,IAAa,WAAb,cAA8B,eAAe;CACzC,KAA2B;CAE3B,cAAyC;EACrC,OAAO,EAAE,MAAM,MAAM;CACzB;CAEA,WAAqB,OAAiC;EAClD,OAAO,wBAAwB,MAAM,MAAM;CAC/C;AACJ;;;;;;AAOA,SAAgB,wBAAwB,QAAwC;CAC5E,OAAO,OAAO,KAAI,UACd,UAAU,QAAQ,QAAQ,IAAI;EAAE;EAAO,WAAW,EAAE,OAAO,qBAAqB;CAAE,IAAI,KAC1F;AACJ"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { BarSeriesOption, EChartsOption, LineSeriesOption } from 'echarts';
|
|
2
|
+
import { ChartData, ChartSeries } from './ChartSeries';
|
|
3
|
+
import { ChartContext, ChartType } from './ChartType';
|
|
4
|
+
import { ChartTypeId } from './ChartTypeId';
|
|
5
|
+
/** Column or line series, the two formats used in the charts with axes (cartesian). */
|
|
6
|
+
export type CartesianSeries = BarSeriesOption | LineSeriesOption;
|
|
7
|
+
/** Value of a category in a series, in the format accepted by `series[i].data` (with or without its own style). */
|
|
8
|
+
export type DataPoint = number | null | {
|
|
9
|
+
value: number;
|
|
10
|
+
itemStyle: {
|
|
11
|
+
color: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Base of the chart types with an X axis of categories (line, columns, stacked columns).
|
|
16
|
+
* It builds the panels per unit, the header and the tooltip, leaving to each type just the style of each series.
|
|
17
|
+
* @author Manoel Campos
|
|
18
|
+
*/
|
|
19
|
+
export declare abstract class CartesianChart implements ChartType {
|
|
20
|
+
abstract readonly id: ChartTypeId;
|
|
21
|
+
readonly singleCategory = false;
|
|
22
|
+
/** Types with axes work for any set of series, except the ones that restrict it (see the subclasses). */
|
|
23
|
+
isAvailable(series: ChartSeries[]): boolean;
|
|
24
|
+
buildOption(data: ChartData, context: ChartContext): EChartsOption;
|
|
25
|
+
height(data: ChartData, context: ChartContext): number;
|
|
26
|
+
/**
|
|
27
|
+
* Defines how a series is drawn (type, stacking etc.).
|
|
28
|
+
* @param serie series to draw
|
|
29
|
+
* @param all all series of the chart, for types that depend on the whole set (e.g. stacking)
|
|
30
|
+
* @return the style of the series in the ECharts format, without name, data and axes (filled by the base)
|
|
31
|
+
*/
|
|
32
|
+
protected abstract seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries;
|
|
33
|
+
/**
|
|
34
|
+
* Values of the series in the `series[i].data` format. By default, the values themselves; subclasses may give
|
|
35
|
+
* their own style to some values (e.g. negative values).
|
|
36
|
+
* @param serie series of the chart
|
|
37
|
+
* @return one value per category
|
|
38
|
+
*/
|
|
39
|
+
protected seriesData(serie: ChartSeries): DataPoint[];
|
|
40
|
+
/**
|
|
41
|
+
* Creates the complete ECharts series: style of the type, name, values, axes of the panel and tooltip format.
|
|
42
|
+
* @param serie series of the chart
|
|
43
|
+
* @param all all series of the chart
|
|
44
|
+
* @param panelIndex index of the panel (and of the axes) of the unit of the series
|
|
45
|
+
* @return the series in the ECharts format
|
|
46
|
+
*/
|
|
47
|
+
private buildSeries;
|
|
48
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { chartLocale, chartMessages } from "./ChartTexts.js";
|
|
3
|
+
import { buildPanelAxes, groupByUnit, panelsHeight } from "./UnitPanels.js";
|
|
4
|
+
import { buildChartHeader, legendExtraHeight, tooltipFormatter } from "./ChartHeader.js";
|
|
5
|
+
// src/component/organism/EChart/chart/CartesianChart.ts
|
|
6
|
+
/**
|
|
7
|
+
* Base of the chart types with an X axis of categories (line, columns, stacked columns).
|
|
8
|
+
* It builds the panels per unit, the header and the tooltip, leaving to each type just the style of each series.
|
|
9
|
+
* @author Manoel Campos
|
|
10
|
+
*/
|
|
11
|
+
var CartesianChart = class {
|
|
12
|
+
singleCategory = false;
|
|
13
|
+
/** Types with axes work for any set of series, except the ones that restrict it (see the subclasses). */
|
|
14
|
+
isAvailable(series) {
|
|
15
|
+
return series.length > 0;
|
|
16
|
+
}
|
|
17
|
+
buildOption(data, context) {
|
|
18
|
+
const panels = groupByUnit(data.series);
|
|
19
|
+
const series = panels.flatMap((panel, index) => panel.series.map((serie) => this.buildSeries(serie, data.series, index)));
|
|
20
|
+
const names = data.series.map((serie) => serie.name);
|
|
21
|
+
const extraTop = legendExtraHeight(names, context.width);
|
|
22
|
+
return {
|
|
23
|
+
...buildChartHeader(context.title, names, chartMessages(context)),
|
|
24
|
+
tooltip: { trigger: "axis" },
|
|
25
|
+
...buildPanelAxes(panels, data.categories, extraTop, chartLocale(context)),
|
|
26
|
+
series
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
height(data, context) {
|
|
30
|
+
const extraTop = legendExtraHeight(data.series.map((serie) => serie.name), context.width);
|
|
31
|
+
return panelsHeight(groupByUnit(data.series).length, data.categories.length, extraTop);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Values of the series in the `series[i].data` format. By default, the values themselves; subclasses may give
|
|
35
|
+
* their own style to some values (e.g. negative values).
|
|
36
|
+
* @param serie series of the chart
|
|
37
|
+
* @return one value per category
|
|
38
|
+
*/
|
|
39
|
+
seriesData(serie) {
|
|
40
|
+
return serie.values;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates the complete ECharts series: style of the type, name, values, axes of the panel and tooltip format.
|
|
44
|
+
* @param serie series of the chart
|
|
45
|
+
* @param all all series of the chart
|
|
46
|
+
* @param panelIndex index of the panel (and of the axes) of the unit of the series
|
|
47
|
+
* @return the series in the ECharts format
|
|
48
|
+
*/
|
|
49
|
+
buildSeries(serie, all, panelIndex) {
|
|
50
|
+
return {
|
|
51
|
+
...this.seriesStyle(serie, all),
|
|
52
|
+
id: serie.id,
|
|
53
|
+
name: serie.name,
|
|
54
|
+
data: this.seriesData(serie),
|
|
55
|
+
xAxisIndex: panelIndex,
|
|
56
|
+
yAxisIndex: panelIndex,
|
|
57
|
+
tooltip: { valueFormatter: tooltipFormatter(serie.unit) }
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
export { CartesianChart };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=CartesianChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CartesianChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/CartesianChart.ts"],"sourcesContent":["import type { BarSeriesOption, EChartsOption, LineSeriesOption } from 'echarts';\n\nimport { ChartData, ChartSeries } from './ChartSeries';\nimport { ChartContext, ChartType } from './ChartType';\nimport { ChartTypeId } from './ChartTypeId';\nimport { chartLocale, chartMessages } from './ChartTexts';\nimport { buildPanelAxes, groupByUnit, panelsHeight } from './UnitPanels';\nimport { buildChartHeader, legendExtraHeight, tooltipFormatter } from './ChartHeader';\n\n/** Column or line series, the two formats used in the charts with axes (cartesian). */\nexport type CartesianSeries = BarSeriesOption | LineSeriesOption;\n\n/** Value of a category in a series, in the format accepted by `series[i].data` (with or without its own style). */\nexport type DataPoint = number | null | { value: number; itemStyle: { color: string } };\n\n/**\n * Base of the chart types with an X axis of categories (line, columns, stacked columns).\n * It builds the panels per unit, the header and the tooltip, leaving to each type just the style of each series.\n * @author Manoel Campos\n */\nexport abstract class CartesianChart implements ChartType {\n abstract readonly id: ChartTypeId;\n readonly singleCategory = false;\n\n /** Types with axes work for any set of series, except the ones that restrict it (see the subclasses). */\n isAvailable(series: ChartSeries[]): boolean {\n return series.length > 0;\n }\n\n buildOption(data: ChartData, context: ChartContext): EChartsOption {\n const panels = groupByUnit(data.series);\n const series = panels.flatMap((panel, index) =>\n panel.series.map(serie => this.buildSeries(serie, data.series, index))\n );\n const names = data.series.map(serie => serie.name);\n const extraTop = legendExtraHeight(names, context.width);\n\n return {\n ...buildChartHeader(context.title, names, chartMessages(context)),\n tooltip: { trigger: 'axis' },\n ...buildPanelAxes(panels, data.categories, extraTop, chartLocale(context)),\n series\n };\n }\n\n height(data: ChartData, context: ChartContext): number {\n const extraTop = legendExtraHeight(\n data.series.map(serie => serie.name),\n context.width\n );\n return panelsHeight(groupByUnit(data.series).length, data.categories.length, extraTop);\n }\n\n /**\n * Defines how a series is drawn (type, stacking etc.).\n * @param serie series to draw\n * @param all all series of the chart, for types that depend on the whole set (e.g. stacking)\n * @return the style of the series in the ECharts format, without name, data and axes (filled by the base)\n */\n protected abstract seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries;\n\n /**\n * Values of the series in the `series[i].data` format. By default, the values themselves; subclasses may give\n * their own style to some values (e.g. negative values).\n * @param serie series of the chart\n * @return one value per category\n */\n protected seriesData(serie: ChartSeries): DataPoint[] {\n return serie.values;\n }\n\n /**\n * Creates the complete ECharts series: style of the type, name, values, axes of the panel and tooltip format.\n * @param serie series of the chart\n * @param all all series of the chart\n * @param panelIndex index of the panel (and of the axes) of the unit of the series\n * @return the series in the ECharts format\n */\n private buildSeries(serie: ChartSeries, all: ChartSeries[], panelIndex: number): CartesianSeries {\n return {\n ...this.seriesStyle(serie, all),\n id: serie.id,\n name: serie.name,\n data: this.seriesData(serie),\n xAxisIndex: panelIndex,\n yAxisIndex: panelIndex,\n tooltip: { valueFormatter: tooltipFormatter(serie.unit) }\n } as CartesianSeries;\n }\n}\n"],"mappings":";;;;;;;;;;AAoBA,IAAsB,iBAAtB,MAA0D;CAEtD,iBAA0B;;CAG1B,YAAY,QAAgC;EACxC,OAAO,OAAO,SAAS;CAC3B;CAEA,YAAY,MAAiB,SAAsC;EAC/D,MAAM,SAAS,YAAY,KAAK,MAAM;EACtC,MAAM,SAAS,OAAO,SAAS,OAAO,UAClC,MAAM,OAAO,KAAI,UAAS,KAAK,YAAY,OAAO,KAAK,QAAQ,KAAK,CAAC,CACzE;EACA,MAAM,QAAQ,KAAK,OAAO,KAAI,UAAS,MAAM,IAAI;EACjD,MAAM,WAAW,kBAAkB,OAAO,QAAQ,KAAK;EAEvD,OAAO;GACH,GAAG,iBAAiB,QAAQ,OAAO,OAAO,cAAc,OAAO,CAAC;GAChE,SAAS,EAAE,SAAS,OAAO;GAC3B,GAAG,eAAe,QAAQ,KAAK,YAAY,UAAU,YAAY,OAAO,CAAC;GACzE;EACJ;CACJ;CAEA,OAAO,MAAiB,SAA+B;EACnD,MAAM,WAAW,kBACb,KAAK,OAAO,KAAI,UAAS,MAAM,IAAI,GACnC,QAAQ,KACZ;EACA,OAAO,aAAa,YAAY,KAAK,MAAM,CAAC,CAAC,QAAQ,KAAK,WAAW,QAAQ,QAAQ;CACzF;;;;;;;CAgBA,WAAqB,OAAiC;EAClD,OAAO,MAAM;CACjB;;;;;;;;CASA,YAAoB,OAAoB,KAAoB,YAAqC;EAC7F,OAAO;GACH,GAAG,KAAK,YAAY,OAAO,GAAG;GAC9B,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,MAAM,KAAK,WAAW,KAAK;GAC3B,YAAY;GACZ,YAAY;GACZ,SAAS,EAAE,gBAAgB,iBAAiB,MAAM,IAAI,EAAE;EAC5D;CACJ;AACJ"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { EChartsOption } from 'echarts';
|
|
2
|
+
import { ChartMessages } from '../../../../i18n/KitMessages';
|
|
3
|
+
import { ChartUnit } from './ChartSeries';
|
|
4
|
+
/** Height of each legend row, including the space until the next one (px). */
|
|
5
|
+
export declare const LEGEND_ROW_HEIGHT: number;
|
|
6
|
+
/**
|
|
7
|
+
* Builds the title, the legend and the image export button.
|
|
8
|
+
* The title also appears in the saved image, so it has context outside the screen.
|
|
9
|
+
* @param title title of the chart
|
|
10
|
+
* @param names names of the series, shown in the legend
|
|
11
|
+
* @param messages texts of the chart; defaults to the one of the default locales
|
|
12
|
+
* @return the parts of the `option` of the header
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildChartHeader(title: string, names: string[], messages?: ChartMessages): Pick<EChartsOption, 'title' | 'legend' | 'toolbox'>;
|
|
15
|
+
/**
|
|
16
|
+
* Creates the function that formats a value in the tooltip with the unit of the series.
|
|
17
|
+
* @param unit unit of the series
|
|
18
|
+
* @return a function that formats the value received from ECharts (or "-" when the category has no value)
|
|
19
|
+
*/
|
|
20
|
+
export declare function tooltipFormatter(unit: ChartUnit): (value: unknown) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Computes the extra height the legend takes when it wraps in more than one row, so the chart is moved down and is
|
|
23
|
+
* not drawn under it.
|
|
24
|
+
* @param names names of the series, shown in the legend
|
|
25
|
+
* @param width width of the chart (px); absent while unknown, considering the legend in one row
|
|
26
|
+
* @return the height of the legend rows beyond the first one (px)
|
|
27
|
+
*/
|
|
28
|
+
export declare function legendExtraHeight(names: string[], width?: number): number;
|
|
29
|
+
/**
|
|
30
|
+
* Estimates in how many rows the legend wraps, placing the items as ECharts does: from left to right, moving to the
|
|
31
|
+
* next row when the next item does not fit.
|
|
32
|
+
* @param names names of the series, shown in the legend
|
|
33
|
+
* @param width width of the chart (px); absent while unknown
|
|
34
|
+
* @return the number of rows of the legend (at least 1)
|
|
35
|
+
*/
|
|
36
|
+
export declare function legendRows(names: string[], width?: number): number;
|