@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,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKitConfig } from "../../../provider/useKit.js";
|
|
3
|
+
import Surface from "../../atom/Surface/Surface.js";
|
|
4
|
+
import Breadcrumb from "../../molecule/Breadcrumb/Breadcrumb.js";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { Button, Divider, Flex, Paper, Stack, Title } from "@mantine/core";
|
|
7
|
+
import { IconPlus } from "@tabler/icons-react";
|
|
8
|
+
// src/component/organism/PageHeader/PageHeader.tsx
|
|
9
|
+
/**
|
|
10
|
+
* Header of a page: the title, the breadcrumb and, in list pages, the "Add" button. With the button, the breadcrumb
|
|
11
|
+
* starts at the home page.
|
|
12
|
+
*/
|
|
13
|
+
var PageHeader = (props) => {
|
|
14
|
+
const { breadcrumbItems, title, addActionRoute, ...others } = props;
|
|
15
|
+
const { router, messages } = useKitConfig();
|
|
16
|
+
const { Link } = router;
|
|
17
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Surface, {
|
|
18
|
+
component: Paper,
|
|
19
|
+
style: { backgroundColor: "transparent" },
|
|
20
|
+
...others,
|
|
21
|
+
children: addActionRoute ? /* @__PURE__ */ jsxs(Flex, {
|
|
22
|
+
align: "center",
|
|
23
|
+
justify: "space-between",
|
|
24
|
+
direction: {
|
|
25
|
+
base: "row",
|
|
26
|
+
sm: "row"
|
|
27
|
+
},
|
|
28
|
+
gap: {
|
|
29
|
+
base: "sm",
|
|
30
|
+
sm: 4
|
|
31
|
+
},
|
|
32
|
+
children: [/* @__PURE__ */ jsxs(Stack, { children: [/* @__PURE__ */ jsx(Title, {
|
|
33
|
+
order: 3,
|
|
34
|
+
children: title
|
|
35
|
+
}), /* @__PURE__ */ jsx(Breadcrumb, { items: [{
|
|
36
|
+
title: messages.common.home,
|
|
37
|
+
href: "/"
|
|
38
|
+
}, ...breadcrumbItems ?? []] })] }), /* @__PURE__ */ jsx(Button, {
|
|
39
|
+
leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 18 }),
|
|
40
|
+
component: Link,
|
|
41
|
+
href: addActionRoute,
|
|
42
|
+
children: messages.common.add
|
|
43
|
+
})]
|
|
44
|
+
}) : /* @__PURE__ */ jsxs(Stack, {
|
|
45
|
+
gap: "sm",
|
|
46
|
+
children: [/* @__PURE__ */ jsx(Title, {
|
|
47
|
+
order: 3,
|
|
48
|
+
children: title
|
|
49
|
+
}), /* @__PURE__ */ jsx(Breadcrumb, { items: breadcrumbItems ?? [] })]
|
|
50
|
+
})
|
|
51
|
+
}), /* @__PURE__ */ jsx(Divider, {})] });
|
|
52
|
+
};
|
|
53
|
+
export { PageHeader as default };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=PageHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PageHeader.js","names":["_Fragment"],"sources":["../../../../src/component/organism/PageHeader/PageHeader.tsx"],"sourcesContent":["'use client';\n\nimport { Button, Divider, Flex, Paper, PaperProps, Stack, Title } from '@mantine/core';\nimport { IconPlus } from '@tabler/icons-react';\n\nimport { useKitConfig } from '../../../provider/useKit';\nimport Surface from '../../atom/Surface/Surface';\nimport Breadcrumb, { BreadcrumbItem } from '../../molecule/Breadcrumb/Breadcrumb';\n\ntype PageHeaderProps = {\n title: string;\n breadcrumbItems?: BreadcrumbItem[];\n\n /** Route of the \"Add\" button. Without it, the page has no \"Add\" button. */\n addActionRoute?: string;\n} & PaperProps;\n\n/**\n * Header of a page: the title, the breadcrumb and, in list pages, the \"Add\" button. With the button, the breadcrumb\n * starts at the home page.\n */\nconst PageHeader = (props: PageHeaderProps) => {\n const { breadcrumbItems, title, addActionRoute, ...others } = props;\n const { router, messages } = useKitConfig();\n const { Link } = router;\n\n return (\n <>\n <Surface component={Paper} style={{ backgroundColor: 'transparent' }} {...others}>\n {addActionRoute ? (\n <Flex\n align=\"center\"\n justify=\"space-between\"\n direction={{ base: 'row', sm: 'row' }}\n gap={{ base: 'sm', sm: 4 }}\n >\n <Stack>\n <Title order={3}>{title}</Title>\n <Breadcrumb\n items={[{ title: messages.common.home, href: '/' }, ...(breadcrumbItems ?? [])]}\n />\n </Stack>\n\n <Button leftSection={<IconPlus size={18} />} component={Link} href={addActionRoute}>\n {messages.common.add}\n </Button>\n </Flex>\n ) : (\n <Stack gap=\"sm\">\n <Title order={3}>{title}</Title>\n <Breadcrumb items={breadcrumbItems ?? []} />\n </Stack>\n )}\n </Surface>\n <Divider />\n </>\n );\n};\n\nexport default PageHeader;\n"],"mappings":";;;;;;;;;;;;AAqBA,IAAM,cAAc,UAA2B;CAC3C,MAAM,EAAE,iBAAiB,OAAO,gBAAgB,GAAG,WAAW;CAC9D,MAAM,EAAE,QAAQ,aAAa,aAAa;CAC1C,MAAM,EAAE,SAAS;CAEjB,OACI,qBAAAA,UAAA,EAAA,UAAA,CACI,oBAAC,SAAD;EAAS,WAAW;EAAO,OAAO,EAAE,iBAAiB,cAAc;EAAG,GAAI;EACrE,UAAA,iBACG,qBAAC,MAAD;GACI,OAAM;GACN,SAAQ;GACR,WAAW;IAAE,MAAM;IAAO,IAAI;GAAM;GACpC,KAAK;IAAE,MAAM;IAAM,IAAI;GAAE;GAJ7B,UAAA,CAMI,qBAAC,OAAD,EAAA,UAAA,CACI,oBAAC,OAAD;IAAO,OAAO;IAAI,UAAA;GAAa,CAAA,GAC/B,oBAAC,YAAD,EACI,OAAO,CAAC;IAAE,OAAO,SAAS,OAAO;IAAM,MAAM;GAAI,GAAG,GAAI,mBAAmB,CAAC,CAAE,EACjF,CAAA,CACE,EAAA,CAAA,GAEP,oBAAC,QAAD;IAAQ,aAAa,oBAAC,UAAD,EAAU,MAAM,GAAK,CAAA;IAAG,WAAW;IAAM,MAAM;IAC/D,UAAA,SAAS,OAAO;GACb,CAAA,CACN;EAEN,CAAA,IAAA,qBAAC,OAAD;GAAO,KAAI;GAAX,UAAA,CACI,oBAAC,OAAD;IAAO,OAAO;IAAI,UAAA;GAAa,CAAA,GAC/B,oBAAC,YAAD,EAAY,OAAO,mBAAmB,CAAC,EAAI,CAAA,CACxC;;CAEN,CAAA,GACT,oBAAC,SAAD,CAAU,CAAA,CACZ,EAAA,CAAA;AAEV"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { PaperProps } from '@mantine/core';
|
|
3
|
+
import { StatsCardData } from '../../molecule/StatsCard/StatsCard';
|
|
4
|
+
type StatsGridProps = {
|
|
5
|
+
data?: StatsCardData[];
|
|
6
|
+
paperProps?: PaperProps;
|
|
7
|
+
error?: ReactNode;
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
};
|
|
10
|
+
/** Responsive grid of {@link StatsCard}s, with placeholders while loading and an alert on error. */
|
|
11
|
+
export default function StatsGrid({ data, loading, error, paperProps }: StatsGridProps): ReactElement;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKitMessages } from "../../../provider/useKit.js";
|
|
3
|
+
import StatsGrid_module_default from "./StatsGrid.module.js";
|
|
4
|
+
import ErrorAlert from "../../atom/ErrorAlert/ErrorAlert.js";
|
|
5
|
+
import StatsCard from "../../molecule/StatsCard/StatsCard.js";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
import { SimpleGrid, Skeleton } from "@mantine/core";
|
|
8
|
+
// src/component/organism/StatsGrid/StatsGrid.tsx
|
|
9
|
+
/** Number of placeholder cards shown while loading. */
|
|
10
|
+
var LOADING_CARDS = 4;
|
|
11
|
+
/** Responsive grid of {@link StatsCard}s, with placeholders while loading and an alert on error. */
|
|
12
|
+
function StatsGrid({ data, loading, error, paperProps }) {
|
|
13
|
+
const messages = useKitMessages();
|
|
14
|
+
const stats = data?.map((stat) => /* @__PURE__ */ jsx(StatsCard, {
|
|
15
|
+
data: stat,
|
|
16
|
+
...paperProps
|
|
17
|
+
}, stat.title));
|
|
18
|
+
return /* @__PURE__ */ jsx("div", {
|
|
19
|
+
className: StatsGrid_module_default.root,
|
|
20
|
+
children: error ? /* @__PURE__ */ jsx(ErrorAlert, {
|
|
21
|
+
title: messages.common.loadError,
|
|
22
|
+
message: String(error)
|
|
23
|
+
}) : /* @__PURE__ */ jsx(SimpleGrid, {
|
|
24
|
+
cols: {
|
|
25
|
+
base: 1,
|
|
26
|
+
sm: 2,
|
|
27
|
+
lg: 4
|
|
28
|
+
},
|
|
29
|
+
spacing: {
|
|
30
|
+
base: 10,
|
|
31
|
+
sm: "xl"
|
|
32
|
+
},
|
|
33
|
+
verticalSpacing: {
|
|
34
|
+
base: "md",
|
|
35
|
+
sm: "xl"
|
|
36
|
+
},
|
|
37
|
+
children: loading ? Array.from({ length: LOADING_CARDS }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, {
|
|
38
|
+
visible: true,
|
|
39
|
+
height: 130
|
|
40
|
+
}, `stats-loading-${i}`)) : stats
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export { StatsGrid as default };
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=StatsGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatsGrid.js","names":["classes"],"sources":["../../../../src/component/organism/StatsGrid/StatsGrid.tsx"],"sourcesContent":["import { ReactElement, ReactNode } from 'react';\n\nimport { PaperProps, SimpleGrid, Skeleton } from '@mantine/core';\n\nimport { useKitMessages } from '../../../provider/useKit';\nimport classes from './StatsGrid.module.css';\nimport ErrorAlert from '../../atom/ErrorAlert/ErrorAlert';\nimport StatsCard, { StatsCardData } from '../../molecule/StatsCard/StatsCard';\n\n/** Number of placeholder cards shown while loading. */\nconst LOADING_CARDS = 4;\n\ntype StatsGridProps = {\n data?: StatsCardData[];\n paperProps?: PaperProps;\n error?: ReactNode;\n loading?: boolean;\n};\n\n/** Responsive grid of {@link StatsCard}s, with placeholders while loading and an alert on error. */\nexport default function StatsGrid({ data, loading, error, paperProps }: StatsGridProps): ReactElement {\n const messages = useKitMessages();\n const stats = data?.map(stat => <StatsCard key={stat.title} data={stat} {...paperProps} />);\n\n return (\n <div className={classes.root}>\n {error ? (\n <ErrorAlert title={messages.common.loadError} message={String(error)} />\n ) : (\n <SimpleGrid\n cols={{ base: 1, sm: 2, lg: 4 }}\n spacing={{ base: 10, sm: 'xl' }}\n verticalSpacing={{ base: 'md', sm: 'xl' }}\n >\n {loading\n ? Array.from({ length: LOADING_CARDS }).map((_, i) => (\n <Skeleton key={`stats-loading-${i}`} visible height={130} />\n ))\n : stats}\n </SimpleGrid>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAUA,IAAM,gBAAgB;;AAUtB,SAAwB,UAAU,EAAE,MAAM,SAAS,OAAO,cAA4C;CAClG,MAAM,WAAW,eAAe;CAChC,MAAM,QAAQ,MAAM,KAAI,SAAQ,oBAAC,WAAD;EAA4B,MAAM;EAAM,GAAI;CAAa,GAAzC,KAAK,KAAoC,CAAC;CAE1F,OACI,oBAAC,OAAD;EAAK,WAAWA,yBAAQ;EACnB,UAAA,QACG,oBAAC,YAAD;GAAY,OAAO,SAAS,OAAO;GAAW,SAAS,OAAO,KAAK;EAAI,CAAA,IAEvE,oBAAC,YAAD;GACI,MAAM;IAAE,MAAM;IAAG,IAAI;IAAG,IAAI;GAAE;GAC9B,SAAS;IAAE,MAAM;IAAI,IAAI;GAAK;GAC9B,iBAAiB;IAAE,MAAM;IAAM,IAAI;GAAK;GAEvC,UAAA,UACK,MAAM,KAAK,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,KAAK,GAAG,MAC1C,oBAAC,UAAD;IAAqC,SAAA;IAAQ,QAAQ;GAAM,GAA5C,iBAAiB,GAA2B,CAC9D,IACD;EACE,CAAA;CAEf,CAAA;AAEb"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// src/component/organism/StatsGrid/StatsGrid.module.css
|
|
3
|
+
var root = "mk-StatsGrid-module-root-zSIO5";
|
|
4
|
+
var value = "mk-StatsGrid-module-value-wk1kb";
|
|
5
|
+
var diff = "mk-StatsGrid-module-diff-AUfON";
|
|
6
|
+
var icon = "mk-StatsGrid-module-icon-ERQtf";
|
|
7
|
+
var title = "mk-StatsGrid-module-title-yuu3f";
|
|
8
|
+
var StatsGrid_module_default = {
|
|
9
|
+
root,
|
|
10
|
+
value,
|
|
11
|
+
diff,
|
|
12
|
+
icon,
|
|
13
|
+
title
|
|
14
|
+
};
|
|
15
|
+
export { StatsGrid_module_default as default, diff, icon, root, title, value };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=StatsGrid.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatsGrid.module.js","names":[],"sources":["../../../../src/component/organism/StatsGrid/StatsGrid.module.css"],"sourcesContent":[".root {\n padding: 0;\n}\n\n.value {\n font-size: rem(24px);\n font-weight: 500;\n line-height: 1;\n}\n\n.diff {\n line-height: 1;\n display: flex;\n align-items: center;\n}\n\n.icon {\n @mixin dark {\n color: var(--mantine-color-dark-3);\n }\n\n @mixin light {\n color: var(--mantine-color-gray-4);\n }\n}\n\n.title {\n font-weight: 500;\n text-transform: uppercase;\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
/** Which actions of a row are shown. */
|
|
3
|
+
export type RowActionsSettings = {
|
|
4
|
+
canView?: boolean;
|
|
5
|
+
canEdit?: boolean;
|
|
6
|
+
canDelete?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type Props = RowActionsSettings & {
|
|
9
|
+
/** URL opened by the view action. */
|
|
10
|
+
viewUrl: string;
|
|
11
|
+
/** URL opened by the edit action, when there is no `onEdit`; absent for a record not saved yet. */
|
|
12
|
+
editUrl?: string;
|
|
13
|
+
/** Called by the edit action instead of opening `editUrl` (e.g. to edit the row in place). */
|
|
14
|
+
onEdit?: () => void;
|
|
15
|
+
/** Called after the user confirms the deletion. */
|
|
16
|
+
onDelete: () => void;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Action buttons of a table row: view, edit and delete (with confirmation). It reads the router and the texts from
|
|
20
|
+
* the `KitProvider`, so the table does not need to pass them down.
|
|
21
|
+
*/
|
|
22
|
+
declare function RowActions({ canView, canEdit, canDelete, viewUrl, editUrl, onEdit, onDelete }: Props): ReactElement;
|
|
23
|
+
export default RowActions;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKitMessages, useKitRouter } from "../../../provider/useKit.js";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { ActionIcon, Button, Group, Text, Tooltip } from "@mantine/core";
|
|
5
|
+
import { IconEdit, IconEye, IconTrash } from "@tabler/icons-react";
|
|
6
|
+
import { closeAllModals, openModal } from "@mantine/modals";
|
|
7
|
+
// src/component/organism/Table/RowActions.tsx
|
|
8
|
+
/** Size of the action icons (px). */
|
|
9
|
+
var ICON_SIZE = 16;
|
|
10
|
+
/**
|
|
11
|
+
* Stops the click on an action from reaching the row, which would navigate again and duplicate the history entry.
|
|
12
|
+
* @param event click event
|
|
13
|
+
*/
|
|
14
|
+
var stopPropagation = (event) => event.stopPropagation();
|
|
15
|
+
/**
|
|
16
|
+
* Asks the user to confirm the deletion of a record.
|
|
17
|
+
* @param messages texts of the table
|
|
18
|
+
* @param cancelLabel text of the cancel button
|
|
19
|
+
* @param confirmLabel text of the confirm button
|
|
20
|
+
* @param onConfirm called when the user confirms
|
|
21
|
+
*/
|
|
22
|
+
function openDeleteModal(messages, { cancelLabel, confirmLabel, title }, onConfirm) {
|
|
23
|
+
openModal({
|
|
24
|
+
title,
|
|
25
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text, { children: messages.deleteConfirm }), /* @__PURE__ */ jsxs(Group, {
|
|
26
|
+
mt: "md",
|
|
27
|
+
gap: "sm",
|
|
28
|
+
justify: "flex-end",
|
|
29
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
30
|
+
variant: "transparent",
|
|
31
|
+
c: "dimmed",
|
|
32
|
+
onClick: () => closeAllModals(),
|
|
33
|
+
children: cancelLabel
|
|
34
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
35
|
+
color: "red",
|
|
36
|
+
onClick: () => {
|
|
37
|
+
onConfirm();
|
|
38
|
+
closeAllModals();
|
|
39
|
+
},
|
|
40
|
+
children: confirmLabel
|
|
41
|
+
})]
|
|
42
|
+
})] })
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Action buttons of a table row: view, edit and delete (with confirmation). It reads the router and the texts from
|
|
47
|
+
* the `KitProvider`, so the table does not need to pass them down.
|
|
48
|
+
*/
|
|
49
|
+
function RowActions({ canView, canEdit, canDelete, viewUrl, editUrl, onEdit, onDelete }) {
|
|
50
|
+
const { Link } = useKitRouter();
|
|
51
|
+
const { table, common } = useKitMessages();
|
|
52
|
+
const modalTexts = {
|
|
53
|
+
title: common.warning,
|
|
54
|
+
cancelLabel: common.cancel,
|
|
55
|
+
confirmLabel: common.confirm
|
|
56
|
+
};
|
|
57
|
+
return /* @__PURE__ */ jsxs(Group, {
|
|
58
|
+
gap: 4,
|
|
59
|
+
justify: "right",
|
|
60
|
+
wrap: "nowrap",
|
|
61
|
+
children: [
|
|
62
|
+
canView && /* @__PURE__ */ jsx(Tooltip, {
|
|
63
|
+
label: table.view,
|
|
64
|
+
children: /* @__PURE__ */ jsx(ActionIcon, {
|
|
65
|
+
size: "sm",
|
|
66
|
+
variant: "subtle",
|
|
67
|
+
color: "green",
|
|
68
|
+
component: Link,
|
|
69
|
+
onClick: stopPropagation,
|
|
70
|
+
href: viewUrl,
|
|
71
|
+
"aria-label": table.view,
|
|
72
|
+
children: /* @__PURE__ */ jsx(IconEye, { size: ICON_SIZE })
|
|
73
|
+
})
|
|
74
|
+
}),
|
|
75
|
+
canEdit && onEdit && /* @__PURE__ */ jsx(Tooltip, {
|
|
76
|
+
label: table.edit,
|
|
77
|
+
children: /* @__PURE__ */ jsx(ActionIcon, {
|
|
78
|
+
size: "sm",
|
|
79
|
+
variant: "subtle",
|
|
80
|
+
color: "blue",
|
|
81
|
+
onClick: (event) => {
|
|
82
|
+
stopPropagation(event);
|
|
83
|
+
onEdit();
|
|
84
|
+
},
|
|
85
|
+
"aria-label": table.edit,
|
|
86
|
+
children: /* @__PURE__ */ jsx(IconEdit, { size: ICON_SIZE })
|
|
87
|
+
})
|
|
88
|
+
}),
|
|
89
|
+
canEdit && !onEdit && editUrl && /* @__PURE__ */ jsx(Tooltip, {
|
|
90
|
+
label: table.edit,
|
|
91
|
+
children: /* @__PURE__ */ jsx(ActionIcon, {
|
|
92
|
+
size: "sm",
|
|
93
|
+
variant: "subtle",
|
|
94
|
+
color: "blue",
|
|
95
|
+
component: Link,
|
|
96
|
+
onClick: stopPropagation,
|
|
97
|
+
href: editUrl,
|
|
98
|
+
"aria-label": table.edit,
|
|
99
|
+
children: /* @__PURE__ */ jsx(IconEdit, { size: ICON_SIZE })
|
|
100
|
+
})
|
|
101
|
+
}),
|
|
102
|
+
canDelete && /* @__PURE__ */ jsx(Tooltip, {
|
|
103
|
+
label: table.delete,
|
|
104
|
+
children: /* @__PURE__ */ jsx(ActionIcon, {
|
|
105
|
+
size: "sm",
|
|
106
|
+
variant: "subtle",
|
|
107
|
+
color: "red",
|
|
108
|
+
onClick: (event) => {
|
|
109
|
+
stopPropagation(event);
|
|
110
|
+
openDeleteModal(table, modalTexts, onDelete);
|
|
111
|
+
},
|
|
112
|
+
"aria-label": table.delete,
|
|
113
|
+
children: /* @__PURE__ */ jsx(IconTrash, { size: ICON_SIZE })
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
]
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
export { RowActions as default };
|
|
120
|
+
|
|
121
|
+
//# sourceMappingURL=RowActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RowActions.js","names":["_Fragment"],"sources":["../../../../src/component/organism/Table/RowActions.tsx"],"sourcesContent":["import { ReactElement } from 'react';\n\nimport { ActionIcon, Button, Group, Text, Tooltip } from '@mantine/core';\nimport { closeAllModals, openModal } from '@mantine/modals';\nimport { IconEdit, IconEye, IconTrash } from '@tabler/icons-react';\n\nimport { TableMessages } from '../../../i18n/KitMessages';\nimport { useKitMessages, useKitRouter } from '../../../provider/useKit';\n\n/** Size of the action icons (px). */\nconst ICON_SIZE = 16;\n\n/** Which actions of a row are shown. */\nexport type RowActionsSettings = {\n canView?: boolean;\n canEdit?: boolean;\n canDelete?: boolean;\n};\n\ntype Props = RowActionsSettings & {\n /** URL opened by the view action. */\n viewUrl: string;\n\n /** URL opened by the edit action, when there is no `onEdit`; absent for a record not saved yet. */\n editUrl?: string;\n\n /** Called by the edit action instead of opening `editUrl` (e.g. to edit the row in place). */\n onEdit?: () => void;\n\n /** Called after the user confirms the deletion. */\n onDelete: () => void;\n};\n\n/**\n * Stops the click on an action from reaching the row, which would navigate again and duplicate the history entry.\n * @param event click event\n */\nconst stopPropagation = (event: React.MouseEvent): void => event.stopPropagation();\n\n/**\n * Asks the user to confirm the deletion of a record.\n * @param messages texts of the table\n * @param cancelLabel text of the cancel button\n * @param confirmLabel text of the confirm button\n * @param onConfirm called when the user confirms\n */\nfunction openDeleteModal(\n messages: TableMessages,\n { cancelLabel, confirmLabel, title }: { cancelLabel: string; confirmLabel: string; title: string },\n onConfirm: () => void\n): void {\n openModal({\n title,\n children: (\n <>\n <Text>{messages.deleteConfirm}</Text>\n\n <Group mt=\"md\" gap=\"sm\" justify=\"flex-end\">\n <Button variant=\"transparent\" c=\"dimmed\" onClick={() => closeAllModals()}>\n {cancelLabel}\n </Button>\n <Button\n color=\"red\"\n onClick={() => {\n onConfirm();\n closeAllModals();\n }}\n >\n {confirmLabel}\n </Button>\n </Group>\n </>\n )\n });\n}\n\n/**\n * Action buttons of a table row: view, edit and delete (with confirmation). It reads the router and the texts from\n * the `KitProvider`, so the table does not need to pass them down.\n */\nfunction RowActions({ canView, canEdit, canDelete, viewUrl, editUrl, onEdit, onDelete }: Props): ReactElement {\n const { Link } = useKitRouter();\n const { table, common } = useKitMessages();\n const modalTexts = { title: common.warning, cancelLabel: common.cancel, confirmLabel: common.confirm };\n\n return (\n <Group gap={4} justify=\"right\" wrap=\"nowrap\">\n {canView && (\n <Tooltip label={table.view}>\n <ActionIcon\n size=\"sm\"\n variant=\"subtle\"\n color=\"green\"\n component={Link}\n onClick={stopPropagation}\n href={viewUrl}\n aria-label={table.view}\n >\n <IconEye size={ICON_SIZE} />\n </ActionIcon>\n </Tooltip>\n )}\n\n {canEdit && onEdit && (\n <Tooltip label={table.edit}>\n <ActionIcon\n size=\"sm\"\n variant=\"subtle\"\n color=\"blue\"\n onClick={event => {\n stopPropagation(event);\n onEdit();\n }}\n aria-label={table.edit}\n >\n <IconEdit size={ICON_SIZE} />\n </ActionIcon>\n </Tooltip>\n )}\n\n {canEdit && !onEdit && editUrl && (\n <Tooltip label={table.edit}>\n <ActionIcon\n size=\"sm\"\n variant=\"subtle\"\n color=\"blue\"\n component={Link}\n onClick={stopPropagation}\n href={editUrl}\n aria-label={table.edit}\n >\n <IconEdit size={ICON_SIZE} />\n </ActionIcon>\n </Tooltip>\n )}\n\n {canDelete && (\n <Tooltip label={table.delete}>\n <ActionIcon\n size=\"sm\"\n variant=\"subtle\"\n color=\"red\"\n onClick={event => {\n stopPropagation(event);\n openDeleteModal(table, modalTexts, onDelete);\n }}\n aria-label={table.delete}\n >\n <IconTrash size={ICON_SIZE} />\n </ActionIcon>\n </Tooltip>\n )}\n </Group>\n );\n}\n\nexport default RowActions;\n"],"mappings":";;;;;;;;AAUA,IAAM,YAAY;;;;;AA2BlB,IAAM,mBAAmB,UAAkC,MAAM,gBAAgB;;;;;;;;AASjF,SAAS,gBACL,UACA,EAAE,aAAa,cAAc,SAC7B,WACI;CACJ,UAAU;EACN;EACA,UACI,qBAAAA,UAAA,EAAA,UAAA,CACI,oBAAC,MAAD,EAAA,UAAO,SAAS,cAAoB,CAAA,GAEpC,qBAAC,OAAD;GAAO,IAAG;GAAK,KAAI;GAAK,SAAQ;GAAhC,UAAA,CACI,oBAAC,QAAD;IAAQ,SAAQ;IAAc,GAAE;IAAS,eAAe,eAAe;IAClE,UAAA;GACG,CAAA,GACR,oBAAC,QAAD;IACI,OAAM;IACN,eAAe;KACX,UAAU;KACV,eAAe;IACnB;IAEC,UAAA;GACG,CAAA,CACL;EACT,CAAA,CAAA,EAAA,CAAA;CAEV,CAAC;AACL;;;;;AAMA,SAAS,WAAW,EAAE,SAAS,SAAS,WAAW,SAAS,SAAS,QAAQ,YAAiC;CAC1G,MAAM,EAAE,SAAS,aAAa;CAC9B,MAAM,EAAE,OAAO,WAAW,eAAe;CACzC,MAAM,aAAa;EAAE,OAAO,OAAO;EAAS,aAAa,OAAO;EAAQ,cAAc,OAAO;CAAQ;CAErG,OACI,qBAAC,OAAD;EAAO,KAAK;EAAG,SAAQ;EAAQ,MAAK;EAApC,UAAA;GACK,WACG,oBAAC,SAAD;IAAS,OAAO,MAAM;IAClB,UAAA,oBAAC,YAAD;KACI,MAAK;KACL,SAAQ;KACR,OAAM;KACN,WAAW;KACX,SAAS;KACT,MAAM;KACN,cAAY,MAAM;KAElB,UAAA,oBAAC,SAAD,EAAS,MAAM,UAAY,CAAA;IACnB,CAAA;GACP,CAAA;GAGZ,WAAW,UACR,oBAAC,SAAD;IAAS,OAAO,MAAM;IAClB,UAAA,oBAAC,YAAD;KACI,MAAK;KACL,SAAQ;KACR,OAAM;KACN,UAAS,UAAS;MACd,gBAAgB,KAAK;MACrB,OAAO;KACX;KACA,cAAY,MAAM;KAElB,UAAA,oBAAC,UAAD,EAAU,MAAM,UAAY,CAAA;IACpB,CAAA;GACP,CAAA;GAGZ,WAAW,CAAC,UAAU,WACnB,oBAAC,SAAD;IAAS,OAAO,MAAM;IAClB,UAAA,oBAAC,YAAD;KACI,MAAK;KACL,SAAQ;KACR,OAAM;KACN,WAAW;KACX,SAAS;KACT,MAAM;KACN,cAAY,MAAM;KAElB,UAAA,oBAAC,UAAD,EAAU,MAAM,UAAY,CAAA;IACpB,CAAA;GACP,CAAA;GAGZ,aACG,oBAAC,SAAD;IAAS,OAAO,MAAM;IAClB,UAAA,oBAAC,YAAD;KACI,MAAK;KACL,SAAQ;KACR,OAAM;KACN,UAAS,UAAS;MACd,gBAAgB,KAAK;MACrB,gBAAgB,OAAO,YAAY,QAAQ;KAC/C;KACA,cAAY,MAAM;KAElB,UAAA,oBAAC,WAAD,EAAW,MAAM,UAAY,CAAA;IACrB,CAAA;GACP,CAAA;EAEV;;AAEf"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import { DataTableColumn } from 'mantine-datatable';
|
|
3
|
+
import { ListDataSource } from '../../../data/ListDataSource';
|
|
4
|
+
import { Identifiable } from '../../../model/Identifiable';
|
|
5
|
+
/** Which actions the table shows for each record. */
|
|
6
|
+
export type ActionsSettings = {
|
|
7
|
+
/** Whether the actions column is shown. */
|
|
8
|
+
canShowActions: boolean;
|
|
9
|
+
/** Whether the view action is shown. */
|
|
10
|
+
canView: boolean;
|
|
11
|
+
/** Whether the edit action is shown. */
|
|
12
|
+
canEdit: boolean;
|
|
13
|
+
/** Whether the delete action is shown. */
|
|
14
|
+
canDelete: boolean;
|
|
15
|
+
};
|
|
16
|
+
/** Props of the {@link Table}. */
|
|
17
|
+
type TableProps<M extends Identifiable, S extends ListDataSource<M>> = {
|
|
18
|
+
/** Source of the records and of their deletion (e.g. a service that accesses an API). */
|
|
19
|
+
service: S;
|
|
20
|
+
/**
|
|
21
|
+
* Fetches the records shown, instead of `service.findAll()`. To show data already available, use
|
|
22
|
+
* `() => Promise.resolve(data)`.
|
|
23
|
+
*/
|
|
24
|
+
customFetchMethod?: () => Promise<M[]>;
|
|
25
|
+
/** Columns of the table. */
|
|
26
|
+
columns: DataTableColumn<M>[];
|
|
27
|
+
/** Base path of the pages of the records (e.g. `/region`), used to build the view and edit URLs. */
|
|
28
|
+
basePath: string;
|
|
29
|
+
/** Which actions are shown; the ones not given are shown. */
|
|
30
|
+
actionsSettings?: Partial<ActionsSettings>;
|
|
31
|
+
/** Whether the table is paginated. */
|
|
32
|
+
pagination?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Called by the edit action instead of opening the edit page of the record.
|
|
35
|
+
* @param itemId id of the record to edit
|
|
36
|
+
*/
|
|
37
|
+
customEditFunction?: (itemId: M['id']) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Builds the URL opened to view a record (click on the row or on the view icon).
|
|
40
|
+
* If absent, the default route is used: `${basePath}/<view segment>/${item.id}`.
|
|
41
|
+
*/
|
|
42
|
+
getViewUrl?: (item: M) => string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A table that shows the records of a data source, with the view, edit and delete actions. Clicking a row opens the
|
|
46
|
+
* record.
|
|
47
|
+
* @template M type of the records, shown one per row
|
|
48
|
+
* @template S source of the records (e.g. a service that accesses an API)
|
|
49
|
+
*/
|
|
50
|
+
declare const Table: <M extends Identifiable, S extends ListDataSource<M>>(props: TableProps<M, S>) => ReactElement;
|
|
51
|
+
export default Table;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import ViewTable from "../ViewTable/ViewTable.js";
|
|
3
|
+
import RowActions from "./RowActions.js";
|
|
4
|
+
import { useKitConfig } from "../../../provider/useKit.js";
|
|
5
|
+
import ErrorAlert from "../../atom/ErrorAlert/ErrorAlert.js";
|
|
6
|
+
import useService from "../../../hook/useService.js";
|
|
7
|
+
import { showErrorNotification, showSuccessNotification } from "../../../util/Notifications.js";
|
|
8
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
9
|
+
import { jsx } from "react/jsx-runtime";
|
|
10
|
+
import { Box } from "@mantine/core";
|
|
11
|
+
// src/component/organism/Table/Table.tsx
|
|
12
|
+
var ROW_HOVER_COLOR = "var(--mantine-primary-color-light)";
|
|
13
|
+
/** Every action shown, used for the settings the caller does not give. */
|
|
14
|
+
var DEFAULT_ACTIONS_SETTINGS = {
|
|
15
|
+
canShowActions: true,
|
|
16
|
+
canView: true,
|
|
17
|
+
canEdit: true,
|
|
18
|
+
canDelete: true
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Returns the view URL of a record: the one of `getViewUrl`, if given; otherwise, the default view route.
|
|
22
|
+
* @param props props of the table
|
|
23
|
+
* @param item record
|
|
24
|
+
* @param segments URL segments of the form pages
|
|
25
|
+
*/
|
|
26
|
+
function viewUrl(props, item, segments) {
|
|
27
|
+
return props.getViewUrl ? props.getViewUrl(item) : `${props.basePath}/${segments.view}/${item.id}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates the function that deletes a record and reloads the table.
|
|
31
|
+
* @param setData function that sets the records of the table, obtained from `useState`
|
|
32
|
+
* @param service source of the records, which deletes them
|
|
33
|
+
* @param fetchMethod fetches the records again after the deletion
|
|
34
|
+
* @param messages texts of the locale
|
|
35
|
+
* @return a function that receives the record to delete and returns a promise resolved when it is deleted
|
|
36
|
+
*/
|
|
37
|
+
function getDeleteRecordFn(setData, service, fetchMethod, messages) {
|
|
38
|
+
return async (item) => {
|
|
39
|
+
const id = item?.id ?? 0;
|
|
40
|
+
if (!id) {
|
|
41
|
+
setData((prevData) => prevData.filter((current) => current !== item));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
await service.delete(id);
|
|
46
|
+
showSuccessNotification(messages.table.deleteSuccess, messages.common.success);
|
|
47
|
+
setData(await fetchMethod());
|
|
48
|
+
} catch (e) {
|
|
49
|
+
showErrorNotification(e, void 0, messages.common.error);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A table that shows the records of a data source, with the view, edit and delete actions. Clicking a row opens the
|
|
55
|
+
* record.
|
|
56
|
+
* @template M type of the records, shown one per row
|
|
57
|
+
* @template S source of the records (e.g. a service that accesses an API)
|
|
58
|
+
*/
|
|
59
|
+
var Table = (props) => {
|
|
60
|
+
const { customFetchMethod, service, columns, basePath, customEditFunction } = props;
|
|
61
|
+
const fetchMethod = useCallback(() => customFetchMethod ? customFetchMethod() : service.findAll(), [customFetchMethod, service]);
|
|
62
|
+
const { router, messages, formRouteSegments } = useKitConfig();
|
|
63
|
+
const navigate = router.useNavigate();
|
|
64
|
+
const settings = {
|
|
65
|
+
...DEFAULT_ACTIONS_SETTINGS,
|
|
66
|
+
...props.actionsSettings
|
|
67
|
+
};
|
|
68
|
+
const { data: fetchedData, loading, error } = useService(fetchMethod);
|
|
69
|
+
const [data, setData] = useState([]);
|
|
70
|
+
useEffect(() => setData(fetchedData), [fetchedData]);
|
|
71
|
+
const deleteRecord = useMemo(() => getDeleteRecordFn(setData, service, fetchMethod, messages), [
|
|
72
|
+
service,
|
|
73
|
+
fetchMethod,
|
|
74
|
+
messages
|
|
75
|
+
]);
|
|
76
|
+
const actionsColumn = {
|
|
77
|
+
accessor: "actions",
|
|
78
|
+
title: /* @__PURE__ */ jsx(Box, {
|
|
79
|
+
mr: 6,
|
|
80
|
+
children: messages.table.actions
|
|
81
|
+
}),
|
|
82
|
+
textAlign: "right",
|
|
83
|
+
render: (item) => /* @__PURE__ */ jsx(RowActions, {
|
|
84
|
+
...settings,
|
|
85
|
+
viewUrl: viewUrl(props, item, formRouteSegments),
|
|
86
|
+
editUrl: item.id ? `${basePath}/${formRouteSegments.edit}/${item.id}` : void 0,
|
|
87
|
+
onEdit: customEditFunction && item.id ? () => customEditFunction(item.id) : void 0,
|
|
88
|
+
onDelete: () => deleteRecord(item)
|
|
89
|
+
})
|
|
90
|
+
};
|
|
91
|
+
const effectiveColumns = settings.canShowActions ? [...columns, actionsColumn] : columns;
|
|
92
|
+
if (error) return /* @__PURE__ */ jsx(ErrorAlert, {
|
|
93
|
+
title: messages.common.loadError,
|
|
94
|
+
message: String(error)
|
|
95
|
+
});
|
|
96
|
+
return /* @__PURE__ */ jsx(ViewTable, {
|
|
97
|
+
data,
|
|
98
|
+
columns: effectiveColumns,
|
|
99
|
+
loading,
|
|
100
|
+
pagination: props.pagination,
|
|
101
|
+
highlightOnHover: true,
|
|
102
|
+
highlightOnHoverColor: ROW_HOVER_COLOR,
|
|
103
|
+
onRowClick: ({ record }) => navigate(viewUrl(props, record, formRouteSegments))
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
export { Table as default };
|
|
107
|
+
|
|
108
|
+
//# sourceMappingURL=Table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Table.js","names":[],"sources":["../../../../src/component/organism/Table/Table.tsx"],"sourcesContent":["'use client';\n\nimport { ReactElement, useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { Box } from '@mantine/core';\nimport { DataTableColumn } from 'mantine-datatable';\n\nimport ViewTable from '../ViewTable/ViewTable';\nimport RowActions from './RowActions';\nimport { ListDataSource } from '../../../data/ListDataSource';\nimport { KitMessages } from '../../../i18n/KitMessages';\nimport { Identifiable } from '../../../model/Identifiable';\nimport { useKitConfig } from '../../../provider/useKit';\nimport { FormRouteSegments } from '../../../router/FormRouteSegments';\nimport ErrorAlert from '../../atom/ErrorAlert/ErrorAlert';\nimport useService from '../../../hook/useService';\nimport { showErrorNotification, showSuccessNotification } from '../../../util/Notifications';\n\n/*\nColor of the row under the mouse. The default color of mantine-datatable (gray-1) is barely distinguishable from the\nzebra stripes (gray-0), so the highlight went unnoticed. The light variant of the primary color adapts to the light and\ndark color schemes.\n*/\nconst ROW_HOVER_COLOR = 'var(--mantine-primary-color-light)';\n\n/** Which actions the table shows for each record. */\nexport type ActionsSettings = {\n /** Whether the actions column is shown. */\n canShowActions: boolean;\n\n /** Whether the view action is shown. */\n canView: boolean;\n\n /** Whether the edit action is shown. */\n canEdit: boolean;\n\n /** Whether the delete action is shown. */\n canDelete: boolean;\n};\n\n/** Every action shown, used for the settings the caller does not give. */\nconst DEFAULT_ACTIONS_SETTINGS: ActionsSettings = {\n canShowActions: true,\n canView: true,\n canEdit: true,\n canDelete: true\n};\n\n/** Props of the {@link Table}. */\ntype TableProps<M extends Identifiable, S extends ListDataSource<M>> = {\n /** Source of the records and of their deletion (e.g. a service that accesses an API). */\n service: S;\n\n /**\n * Fetches the records shown, instead of `service.findAll()`. To show data already available, use\n * `() => Promise.resolve(data)`.\n */\n customFetchMethod?: () => Promise<M[]>;\n\n /** Columns of the table. */\n columns: DataTableColumn<M>[];\n\n /** Base path of the pages of the records (e.g. `/region`), used to build the view and edit URLs. */\n basePath: string;\n\n /** Which actions are shown; the ones not given are shown. */\n actionsSettings?: Partial<ActionsSettings>;\n\n /** Whether the table is paginated. */\n pagination?: boolean;\n\n /**\n * Called by the edit action instead of opening the edit page of the record.\n * @param itemId id of the record to edit\n */\n customEditFunction?: (itemId: M['id']) => void;\n\n /**\n * Builds the URL opened to view a record (click on the row or on the view icon).\n * If absent, the default route is used: `${basePath}/<view segment>/${item.id}`.\n */\n getViewUrl?: (item: M) => string;\n};\n\n/**\n * Returns the view URL of a record: the one of `getViewUrl`, if given; otherwise, the default view route.\n * @param props props of the table\n * @param item record\n * @param segments URL segments of the form pages\n */\nfunction viewUrl<M extends Identifiable, S extends ListDataSource<M>>(\n props: TableProps<M, S>,\n item: M,\n segments: FormRouteSegments\n): string {\n return props.getViewUrl ? props.getViewUrl(item) : `${props.basePath}/${segments.view}/${item.id}`;\n}\n\n/**\n * Creates the function that deletes a record and reloads the table.\n * @param setData function that sets the records of the table, obtained from `useState`\n * @param service source of the records, which deletes them\n * @param fetchMethod fetches the records again after the deletion\n * @param messages texts of the locale\n * @return a function that receives the record to delete and returns a promise resolved when it is deleted\n */\nfunction getDeleteRecordFn<M extends Identifiable, S extends ListDataSource<M>>(\n setData: (value: ((prevState: M[]) => M[]) | M[]) => void,\n service: S,\n fetchMethod: () => Promise<M[]>,\n messages: KitMessages\n): (item: M) => Promise<void> {\n return async (item: M) => {\n const id = item?.id ?? 0;\n\n // Without an id, the record was added only to the array and was not sent to the backend: just remove it.\n if (!id) {\n setData(prevData => prevData.filter(current => current !== item));\n return;\n }\n\n try {\n await service.delete(id);\n showSuccessNotification(messages.table.deleteSuccess, messages.common.success);\n setData(await fetchMethod());\n } catch (e) {\n showErrorNotification(e, undefined, messages.common.error);\n }\n };\n}\n\n/**\n * A table that shows the records of a data source, with the view, edit and delete actions. Clicking a row opens the\n * record.\n * @template M type of the records, shown one per row\n * @template S source of the records (e.g. a service that accesses an API)\n */\nconst Table = <M extends Identifiable, S extends ListDataSource<M>>(props: TableProps<M, S>): ReactElement => {\n const { customFetchMethod, service, columns, basePath, customEditFunction } = props;\n const fetchMethod = useCallback(\n () => (customFetchMethod ? customFetchMethod() : service.findAll()),\n [customFetchMethod, service]\n );\n const { router, messages, formRouteSegments } = useKitConfig();\n const navigate = router.useNavigate();\n const settings: ActionsSettings = { ...DEFAULT_ACTIONS_SETTINGS, ...props.actionsSettings };\n\n const { data: fetchedData, loading, error } = useService(fetchMethod);\n const [data, setData] = useState<M[]>([]);\n\n useEffect(() => setData(fetchedData), [fetchedData]);\n\n const deleteRecord = useMemo(\n () => getDeleteRecordFn(setData, service, fetchMethod, messages),\n [service, fetchMethod, messages]\n );\n\n const actionsColumn: DataTableColumn<M> = {\n accessor: 'actions',\n title: <Box mr={6}>{messages.table.actions}</Box>,\n textAlign: 'right',\n render: item => (\n <RowActions\n {...settings}\n viewUrl={viewUrl(props, item, formRouteSegments)}\n editUrl={item.id ? `${basePath}/${formRouteSegments.edit}/${item.id}` : undefined}\n onEdit={customEditFunction && item.id ? () => customEditFunction(item.id) : undefined}\n onDelete={() => deleteRecord(item)}\n />\n )\n };\n const effectiveColumns = settings.canShowActions ? [...columns, actionsColumn] : columns;\n\n if (error) {\n return <ErrorAlert title={messages.common.loadError} message={String(error)} />;\n }\n\n return (\n <ViewTable\n data={data}\n columns={effectiveColumns}\n loading={loading}\n pagination={props.pagination}\n // Highlights the row under the mouse, to show that clicking it opens the record, as the view icon does.\n highlightOnHover\n highlightOnHoverColor={ROW_HOVER_COLOR}\n onRowClick={({ record }) => navigate(viewUrl(props, record, formRouteSegments))}\n />\n );\n};\n\nexport default Table;\n"],"mappings":";;;;;;;;;;;AAuBA,IAAM,kBAAkB;;AAkBxB,IAAM,2BAA4C;CAC9C,gBAAgB;CAChB,SAAS;CACT,SAAS;CACT,WAAW;AACf;;;;;;;AA4CA,SAAS,QACL,OACA,MACA,UACM;CACN,OAAO,MAAM,aAAa,MAAM,WAAW,IAAI,IAAI,GAAG,MAAM,SAAS,GAAG,SAAS,KAAK,GAAG,KAAK;AAClG;;;;;;;;;AAUA,SAAS,kBACL,SACA,SACA,aACA,UAC0B;CAC1B,OAAO,OAAO,SAAY;EACtB,MAAM,KAAK,MAAM,MAAM;EAGvB,IAAI,CAAC,IAAI;GACL,SAAQ,aAAY,SAAS,QAAO,YAAW,YAAY,IAAI,CAAC;GAChE;EACJ;EAEA,IAAI;GACA,MAAM,QAAQ,OAAO,EAAE;GACvB,wBAAwB,SAAS,MAAM,eAAe,SAAS,OAAO,OAAO;GAC7E,QAAQ,MAAM,YAAY,CAAC;EAC/B,SAAS,GAAG;GACR,sBAAsB,GAAG,KAAA,GAAW,SAAS,OAAO,KAAK;EAC7D;CACJ;AACJ;;;;;;;AAQA,IAAM,SAA8D,UAA0C;CAC1G,MAAM,EAAE,mBAAmB,SAAS,SAAS,UAAU,uBAAuB;CAC9E,MAAM,cAAc,kBACT,oBAAoB,kBAAkB,IAAI,QAAQ,QAAQ,GACjE,CAAC,mBAAmB,OAAO,CAC/B;CACA,MAAM,EAAE,QAAQ,UAAU,sBAAsB,aAAa;CAC7D,MAAM,WAAW,OAAO,YAAY;CACpC,MAAM,WAA4B;EAAE,GAAG;EAA0B,GAAG,MAAM;CAAgB;CAE1F,MAAM,EAAE,MAAM,aAAa,SAAS,UAAU,WAAW,WAAW;CACpE,MAAM,CAAC,MAAM,WAAW,SAAc,CAAC,CAAC;CAExC,gBAAgB,QAAQ,WAAW,GAAG,CAAC,WAAW,CAAC;CAEnD,MAAM,eAAe,cACX,kBAAkB,SAAS,SAAS,aAAa,QAAQ,GAC/D;EAAC;EAAS;EAAa;CAAQ,CACnC;CAEA,MAAM,gBAAoC;EACtC,UAAU;EACV,OAAO,oBAAC,KAAD;GAAK,IAAI;GAAI,UAAA,SAAS,MAAM;EAAa,CAAA;EAChD,WAAW;EACX,SAAQ,SACJ,oBAAC,YAAD;GACI,GAAI;GACJ,SAAS,QAAQ,OAAO,MAAM,iBAAiB;GAC/C,SAAS,KAAK,KAAK,GAAG,SAAS,GAAG,kBAAkB,KAAK,GAAG,KAAK,OAAO,KAAA;GACxE,QAAQ,sBAAsB,KAAK,WAAW,mBAAmB,KAAK,EAAE,IAAI,KAAA;GAC5E,gBAAgB,aAAa,IAAI;EACpC,CAAA;CAET;CACA,MAAM,mBAAmB,SAAS,iBAAiB,CAAC,GAAG,SAAS,aAAa,IAAI;CAEjF,IAAI,OACA,OAAO,oBAAC,YAAD;EAAY,OAAO,SAAS,OAAO;EAAW,SAAS,OAAO,KAAK;CAAI,CAAA;CAGlF,OACI,oBAAC,WAAD;EACU;EACN,SAAS;EACA;EACT,YAAY,MAAM;EAElB,kBAAA;EACA,uBAAuB;EACvB,aAAa,EAAE,aAAa,SAAS,QAAQ,OAAO,QAAQ,iBAAiB,CAAC;CACjF,CAAA;AAET"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DataTableSortStatus } from 'mantine-datatable';
|
|
2
|
+
/** Comparison function for `Array.prototype.sort`: negative if `a` comes before `b`, positive if it comes after. */
|
|
3
|
+
export type Comparator<M> = (a: M, b: M) => number;
|
|
4
|
+
/**
|
|
5
|
+
* Returns the function that sorts the records by the column and direction chosen in the table header. Texts follow
|
|
6
|
+
* the locale (see {@link compareValues}). Records without a value in the column always come last, so they do not take
|
|
7
|
+
* the first pages in the descending order.
|
|
8
|
+
* @param sortStatus column (path of the attribute, e.g. `city.name`) and direction of the sort
|
|
9
|
+
* @param locale locale of the text comparison; defaults to `en-US`
|
|
10
|
+
*/
|
|
11
|
+
export declare function columnComparator<M>(sortStatus: DataTableSortStatus<M>, locale?: string): Comparator<M>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DEFAULT_LOCALE } from "../../../i18n/KitLocale.js";
|
|
3
|
+
import { compareValues, isAbsent } from "../../../util/CompareUtil.js";
|
|
4
|
+
import { getValueAtPath } from "mantine-datatable";
|
|
5
|
+
// src/component/organism/ViewTable/ColumnComparator.ts
|
|
6
|
+
/**
|
|
7
|
+
* Returns the function that sorts the records by the column and direction chosen in the table header. Texts follow
|
|
8
|
+
* the locale (see {@link compareValues}). Records without a value in the column always come last, so they do not take
|
|
9
|
+
* the first pages in the descending order.
|
|
10
|
+
* @param sortStatus column (path of the attribute, e.g. `city.name`) and direction of the sort
|
|
11
|
+
* @param locale locale of the text comparison; defaults to `en-US`
|
|
12
|
+
*/
|
|
13
|
+
function columnComparator(sortStatus, locale = DEFAULT_LOCALE) {
|
|
14
|
+
const accessor = String(sortStatus.columnAccessor);
|
|
15
|
+
const descending = sortStatus.direction === "desc";
|
|
16
|
+
return (a, b) => {
|
|
17
|
+
const valueA = getValueAtPath(a, accessor);
|
|
18
|
+
const valueB = getValueAtPath(b, accessor);
|
|
19
|
+
const result = compareValues(valueA, valueB, locale);
|
|
20
|
+
return descending && !isAbsent(valueA) && !isAbsent(valueB) ? -result : result;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export { columnComparator };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=ColumnComparator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColumnComparator.js","names":[],"sources":["../../../../src/component/organism/ViewTable/ColumnComparator.ts"],"sourcesContent":["import { DataTableSortStatus, getValueAtPath } from 'mantine-datatable';\n\nimport { DEFAULT_LOCALE } from '../../../i18n/KitLocale';\nimport { compareValues, isAbsent } from '../../../util/CompareUtil';\n\n/** Comparison function for `Array.prototype.sort`: negative if `a` comes before `b`, positive if it comes after. */\nexport type Comparator<M> = (a: M, b: M) => number;\n\n/**\n * Returns the function that sorts the records by the column and direction chosen in the table header. Texts follow\n * the locale (see {@link compareValues}). Records without a value in the column always come last, so they do not take\n * the first pages in the descending order.\n * @param sortStatus column (path of the attribute, e.g. `city.name`) and direction of the sort\n * @param locale locale of the text comparison; defaults to `en-US`\n */\nexport function columnComparator<M>(\n sortStatus: DataTableSortStatus<M>,\n locale: string = DEFAULT_LOCALE\n): Comparator<M> {\n const accessor = String(sortStatus.columnAccessor);\n const descending = sortStatus.direction === 'desc';\n\n return (a, b) => {\n const valueA: unknown = getValueAtPath(a, accessor);\n const valueB: unknown = getValueAtPath(b, accessor);\n const result = compareValues(valueA, valueB, locale);\n\n return descending && !isAbsent(valueA) && !isAbsent(valueB) ? -result : result;\n };\n}\n"],"mappings":";;;;;;;;;;;;AAeA,SAAgB,iBACZ,YACA,SAAiB,gBACJ;CACb,MAAM,WAAW,OAAO,WAAW,cAAc;CACjD,MAAM,aAAa,WAAW,cAAc;CAE5C,QAAQ,GAAG,MAAM;EACb,MAAM,SAAkB,eAAe,GAAG,QAAQ;EAClD,MAAM,SAAkB,eAAe,GAAG,QAAQ;EAClD,MAAM,SAAS,cAAc,QAAQ,QAAQ,MAAM;EAEnD,OAAO,cAAc,CAAC,SAAS,MAAM,KAAK,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS;CAC5E;AACJ"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { DataTableColumn, DataTablePaginationProps, DataTableProps, DataTableSortStatus } from 'mantine-datatable';
|
|
2
|
+
import { Identifiable } from '../../../model/Identifiable';
|
|
3
|
+
import { Comparator } from './ColumnComparator';
|
|
4
|
+
/** Function that defines extra attributes (e.g. aria-label) for each pagination control button. */
|
|
5
|
+
type PaginationControlPropsGetter = Extract<DataTablePaginationProps, {
|
|
6
|
+
page: number;
|
|
7
|
+
}>['getPaginationControlProps'];
|
|
8
|
+
/**
|
|
9
|
+
* Props of the {@link DataTable} passed straight through by the ViewTable.
|
|
10
|
+
* Only the props actually used by the callers are accepted: using `Partial<DataTableProps<M>>` makes TypeScript combine
|
|
11
|
+
* the variants of the `DataTableProps` union with the ones of `paginationProps`, which exhausts the memory of `tsc`.
|
|
12
|
+
*/
|
|
13
|
+
type DataTablePassThroughProps<M extends Identifiable> = Pick<DataTableProps<M>, 'onRowClick' | 'rowStyle' | 'noRecordsText' | 'highlightOnHover' | 'highlightOnHoverColor' | 'className' | 'minHeight' | 'withColumnBorders' | 'verticalSpacing' | 'horizontalSpacing'>;
|
|
14
|
+
/**
|
|
15
|
+
* TableProps is a generic type for the ViewTable component props.
|
|
16
|
+
*/
|
|
17
|
+
type TableProps<M extends Identifiable> = {
|
|
18
|
+
data: M[];
|
|
19
|
+
columns: DataTableColumn<M>[];
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
pagination?: boolean;
|
|
22
|
+
/** Shows the ID column, automatically added to the given columns. */
|
|
23
|
+
showIdColumn?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Initial sort of the table. Default: by `id`, ascending.
|
|
26
|
+
* Give another value when the natural order of the data should not be by `id` (e.g. when the backend already
|
|
27
|
+
* returns the data in an order to keep). Along with `compare`, it only tells which header shows the sort indicator
|
|
28
|
+
* in the initial order.
|
|
29
|
+
*/
|
|
30
|
+
defaultSortStatus?: DataTableSortStatus<M>;
|
|
31
|
+
/**
|
|
32
|
+
* Comparison function that defines the initial order, instead of the column of `defaultSortStatus`. It allows
|
|
33
|
+
* sorting by more than one criterion (e.g. city and, in the same city, year descending). After the user clicks the
|
|
34
|
+
* header of a column, the sort of the column applies.
|
|
35
|
+
*/
|
|
36
|
+
compare?: Comparator<M>;
|
|
37
|
+
/** Extra attributes for the pagination control buttons. It only has effect when `pagination` is true. */
|
|
38
|
+
getPaginationControlProps?: PaginationControlPropsGetter;
|
|
39
|
+
} & DataTablePassThroughProps<M>;
|
|
40
|
+
/**
|
|
41
|
+
* The ViewTable component is a wrapper for the Mantine DataTable component.
|
|
42
|
+
* @template M - Model that extends from {@link Identifiable}
|
|
43
|
+
* @param data the data to be displayed in this ViewTable
|
|
44
|
+
* @param {DataTableColumn<M>[]} columns - The columns to be displayed in this ViewTable
|
|
45
|
+
* @param loading Indicates if the data to be displayed is being loaded yet or not
|
|
46
|
+
* @param pagination Indicates whether to show pagination or not.
|
|
47
|
+
* @param getPaginationControlProps extra attributes for the pagination control buttons
|
|
48
|
+
* @param compare comparison function of the initial order, replaced by the sort of the column chosen in the header
|
|
49
|
+
* @param rest remaining props, passed to the DataTable
|
|
50
|
+
* @return the table with the data, sortable and (optionally) paginated
|
|
51
|
+
*/
|
|
52
|
+
declare const ViewTable: <M extends Identifiable>({ data, columns, loading, pagination, showIdColumn, defaultSortStatus, compare, getPaginationControlProps, ...rest }: TableProps<M>) => import("react/jsx-runtime").JSX.Element;
|
|
53
|
+
export default ViewTable;
|