@omnitron-dev/prism 0.3.1 → 0.3.3
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/README.md +68 -2
- package/THIRD-PARTY-NOTICES.txt +26 -0
- package/dist/accessibility/index.js +2 -0
- package/dist/accessibility/index.js.map +1 -1
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/blocks/auth-block/guards.d.ts +3 -2
- package/dist/blocks/auth-block/guards.d.ts.map +1 -1
- package/dist/blocks/dashboard-block/dashboard-block.d.ts.map +1 -1
- package/dist/blocks/dashboard-block/types.d.ts +4 -2
- package/dist/blocks/dashboard-block/types.d.ts.map +1 -1
- package/dist/blocks/dashboard-block/use-dashboard-block.d.ts +2 -2
- package/dist/blocks/dashboard-block/use-dashboard-block.d.ts.map +1 -1
- package/dist/blocks/data-grid-block/data-grid-block.d.ts.map +1 -1
- package/dist/blocks/data-grid-block/types.d.ts +3 -0
- package/dist/blocks/data-grid-block/types.d.ts.map +1 -1
- package/dist/blocks/index.js +80 -255
- package/dist/blocks/index.js.map +1 -1
- package/dist/chunk-2AB7VGPW.js +447 -0
- package/dist/chunk-2AB7VGPW.js.map +1 -0
- package/dist/{chunk-LOY2NPCO.js → chunk-2E67PQ4T.js} +3 -3
- package/dist/{chunk-LOY2NPCO.js.map → chunk-2E67PQ4T.js.map} +1 -1
- package/dist/chunk-2KG2NI73.js +84 -0
- package/dist/chunk-2KG2NI73.js.map +1 -0
- package/dist/chunk-2UYRW6X3.js +44 -0
- package/dist/chunk-2UYRW6X3.js.map +1 -0
- package/dist/chunk-36C5H56C.js +208 -0
- package/dist/chunk-36C5H56C.js.map +1 -0
- package/dist/chunk-36FOXX25.js +73 -0
- package/dist/chunk-36FOXX25.js.map +1 -0
- package/dist/{chunk-52PQL67Q.js → chunk-3VSM7NZG.js} +18 -15
- package/dist/chunk-3VSM7NZG.js.map +1 -0
- package/dist/{chunk-GUGTDURV.js → chunk-4B2LTPK2.js} +2 -2
- package/dist/{chunk-GUGTDURV.js.map → chunk-4B2LTPK2.js.map} +1 -1
- package/dist/chunk-4HUGZJKU.js +108 -0
- package/dist/chunk-4HUGZJKU.js.map +1 -0
- package/dist/{chunk-PXXPLHIY.js → chunk-4Q5L7LDG.js} +3 -3
- package/dist/{chunk-PXXPLHIY.js.map → chunk-4Q5L7LDG.js.map} +1 -1
- package/dist/{chunk-BRDWQVRT.js → chunk-4R7EZ7GQ.js} +3 -2
- package/dist/chunk-4R7EZ7GQ.js.map +1 -0
- package/dist/chunk-6IANOSMD.js +185 -0
- package/dist/chunk-6IANOSMD.js.map +1 -0
- package/dist/{chunk-YHE7HXSG.js → chunk-7ATBURW2.js} +3 -3
- package/dist/{chunk-YHE7HXSG.js.map → chunk-7ATBURW2.js.map} +1 -1
- package/dist/{chunk-7G5D5PTC.js → chunk-AATAOOSF.js} +4 -4
- package/dist/{chunk-7G5D5PTC.js.map → chunk-AATAOOSF.js.map} +1 -1
- package/dist/chunk-AKLRKCYH.js +128 -0
- package/dist/chunk-AKLRKCYH.js.map +1 -0
- package/dist/chunk-CT46KJOR.js +133 -0
- package/dist/chunk-CT46KJOR.js.map +1 -0
- package/dist/{chunk-LSPFFEJT.js → chunk-D4GFAJAZ.js} +298 -3900
- package/dist/chunk-D4GFAJAZ.js.map +1 -0
- package/dist/{chunk-BJE2AKD4.js → chunk-D5J3KW6Q.js} +3 -2
- package/dist/chunk-D5J3KW6Q.js.map +1 -0
- package/dist/chunk-DEPJRTVT.js +3 -0
- package/dist/{chunk-FU52GL2E.js.map → chunk-DEPJRTVT.js.map} +1 -1
- package/dist/{chunk-472SOF76.js → chunk-DHTYHUYI.js} +85 -107
- package/dist/chunk-DHTYHUYI.js.map +1 -0
- package/dist/{chunk-FF5RF32O.js → chunk-E7WM2RXA.js} +3 -2
- package/dist/chunk-E7WM2RXA.js.map +1 -0
- package/dist/chunk-F6RZ7LW6.js +1271 -0
- package/dist/chunk-F6RZ7LW6.js.map +1 -0
- package/dist/chunk-FOGY3HA4.js +217 -0
- package/dist/chunk-FOGY3HA4.js.map +1 -0
- package/dist/chunk-G2GANYMW.js +139 -0
- package/dist/chunk-G2GANYMW.js.map +1 -0
- package/dist/chunk-I6DILPFE.js +293 -0
- package/dist/chunk-I6DILPFE.js.map +1 -0
- package/dist/{chunk-HOXFSQUV.js → chunk-IRYU3NTG.js} +2 -2
- package/dist/{chunk-HOXFSQUV.js.map → chunk-IRYU3NTG.js.map} +1 -1
- package/dist/chunk-JTIUGPW5.js +284 -0
- package/dist/chunk-JTIUGPW5.js.map +1 -0
- package/dist/{chunk-GUFHFEPZ.js → chunk-JZBSPDED.js} +2 -2
- package/dist/{chunk-GUFHFEPZ.js.map → chunk-JZBSPDED.js.map} +1 -1
- package/dist/{chunk-PFT2BNYO.js → chunk-KPY7TA4D.js} +5 -5
- package/dist/{chunk-PFT2BNYO.js.map → chunk-KPY7TA4D.js.map} +1 -1
- package/dist/{chunk-GMIE6III.js → chunk-LFWKGNCX.js} +50 -623
- package/dist/chunk-LFWKGNCX.js.map +1 -0
- package/dist/chunk-LH4ZZZYB.js +37 -0
- package/dist/chunk-LH4ZZZYB.js.map +1 -0
- package/dist/chunk-NFJ7CPG3.js +13 -0
- package/dist/chunk-NFJ7CPG3.js.map +1 -0
- package/dist/chunk-NFPOIHD4.js +3 -0
- package/dist/{chunk-JSQTYDPG.js.map → chunk-NFPOIHD4.js.map} +1 -1
- package/dist/{chunk-XIXSSI3B.js → chunk-NJM5AVBM.js} +3 -2
- package/dist/chunk-NJM5AVBM.js.map +1 -0
- package/dist/{chunk-4Z5DE5GK.js → chunk-NSNM53WI.js} +133 -115
- package/dist/chunk-NSNM53WI.js.map +1 -0
- package/dist/chunk-NTREGTG7.js +31 -0
- package/dist/chunk-NTREGTG7.js.map +1 -0
- package/dist/{chunk-ADG4HZEP.js → chunk-OKJA6SJM.js} +4 -4
- package/dist/chunk-OKJA6SJM.js.map +1 -0
- package/dist/{chunk-SU3LVQ7N.js → chunk-Q6JDNFSG.js} +11 -226
- package/dist/chunk-Q6JDNFSG.js.map +1 -0
- package/dist/chunk-RPOGINR5.js +115 -0
- package/dist/chunk-RPOGINR5.js.map +1 -0
- package/dist/{chunk-KQ67XB6T.js → chunk-RSWVYIXK.js} +151 -114
- package/dist/chunk-RSWVYIXK.js.map +1 -0
- package/dist/chunk-SSEHL5VP.js +110 -0
- package/dist/chunk-SSEHL5VP.js.map +1 -0
- package/dist/chunk-TEIGUOWN.js +523 -0
- package/dist/chunk-TEIGUOWN.js.map +1 -0
- package/dist/{chunk-AYYFMTMI.js → chunk-TJ7DHXUX.js} +2 -2
- package/dist/{chunk-AYYFMTMI.js.map → chunk-TJ7DHXUX.js.map} +1 -1
- package/dist/{chunk-75FQ5IW3.js → chunk-TZHWYT34.js} +3 -3
- package/dist/{chunk-75FQ5IW3.js.map → chunk-TZHWYT34.js.map} +1 -1
- package/dist/chunk-TZWHELY4.js +45 -0
- package/dist/chunk-TZWHELY4.js.map +1 -0
- package/dist/{chunk-OKTLA23Q.js → chunk-UEINJFLS.js} +6 -6
- package/dist/chunk-UEINJFLS.js.map +1 -0
- package/dist/chunk-URFQX3I6.js +129 -0
- package/dist/chunk-URFQX3I6.js.map +1 -0
- package/dist/chunk-VG6FOMOH.js +187 -0
- package/dist/chunk-VG6FOMOH.js.map +1 -0
- package/dist/{chunk-PGHEP4JD.js → chunk-VQVVHMPG.js} +3 -3
- package/dist/{chunk-PGHEP4JD.js.map → chunk-VQVVHMPG.js.map} +1 -1
- package/dist/{chunk-DRFNMZLG.js → chunk-VUKOT432.js} +3 -2
- package/dist/chunk-VUKOT432.js.map +1 -0
- package/dist/chunk-WD4N72DL.js +315 -0
- package/dist/chunk-WD4N72DL.js.map +1 -0
- package/dist/chunk-XBYMG4QK.js +119 -0
- package/dist/chunk-XBYMG4QK.js.map +1 -0
- package/dist/chunk-YHM6GIHV.js +3 -0
- package/dist/chunk-YHM6GIHV.js.map +1 -0
- package/dist/{chunk-SNZK5X6F.js → chunk-Z2AN43YU.js} +4 -2
- package/dist/chunk-Z2AN43YU.js.map +1 -0
- package/dist/chunk-ZNWHMQRM.js +171 -0
- package/dist/chunk-ZNWHMQRM.js.map +1 -0
- package/dist/{chunk-YSIG2XYH.js → chunk-ZRJYQN6Y.js} +2 -2
- package/dist/{chunk-YSIG2XYH.js.map → chunk-ZRJYQN6Y.js.map} +1 -1
- package/dist/{chunk-AD4W7HYC.js → chunk-ZYI3MHLE.js} +3 -2
- package/dist/chunk-ZYI3MHLE.js.map +1 -0
- package/dist/cli/index.js +59 -421
- package/dist/cli/index.js.map +1 -1
- package/dist/components/admin-filters/admin-data-table.d.ts +7 -1
- package/dist/components/admin-filters/admin-data-table.d.ts.map +1 -1
- package/dist/components/admin-filters/filter-toolbar.d.ts.map +1 -1
- package/dist/components/admin-filters/index.js +8 -0
- package/dist/components/admin-filters/index.js.map +1 -0
- package/dist/components/alert/alert.d.ts.map +1 -1
- package/dist/components/alert/index.js +5 -0
- package/dist/components/alert/index.js.map +1 -0
- package/dist/components/animate/index.js +5 -0
- package/dist/components/animate/index.js.map +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts.map +1 -1
- package/dist/components/breadcrumbs/index.js +4 -0
- package/dist/components/breadcrumbs/index.js.map +1 -0
- package/dist/components/card/index.js +4 -0
- package/dist/components/card/index.js.map +1 -0
- package/dist/components/chart/chart.d.ts.map +1 -1
- package/dist/components/chart/index.css +52 -0
- package/dist/components/chart/index.css.map +1 -0
- package/dist/components/chart/index.js +5 -0
- package/dist/components/chart/index.js.map +1 -0
- package/dist/components/chart/types.d.ts +3 -1
- package/dist/components/chart/types.d.ts.map +1 -1
- package/dist/components/chart/use-chart.d.ts.map +1 -1
- package/dist/components/command-palette/command-palette.d.ts +3 -1
- package/dist/components/command-palette/command-palette.d.ts.map +1 -1
- package/dist/components/command-palette/index.js +4 -0
- package/dist/components/command-palette/index.js.map +1 -0
- package/dist/components/confirm-dialog/index.js +4 -0
- package/dist/components/confirm-dialog/index.js.map +1 -0
- package/dist/components/date-input/date-input.d.ts +1 -0
- package/dist/components/date-input/date-input.d.ts.map +1 -1
- package/dist/components/date-input/index.d.ts +0 -1
- package/dist/components/date-input/index.d.ts.map +1 -1
- package/dist/components/doc-layout/index.js +5 -4
- package/dist/components/doc-layout/index.js.map +1 -1
- package/dist/components/editor/index.js +4 -3
- package/dist/components/editor/index.js.map +1 -1
- package/dist/components/emoji-picker/index.js +2 -1
- package/dist/components/emoji-picker/index.js.map +1 -1
- package/dist/components/empty-content/empty-content.d.ts.map +1 -1
- package/dist/components/empty-content/index.js +4 -0
- package/dist/components/empty-content/index.js.map +1 -0
- package/dist/components/error-boundary/index.js +6 -0
- package/dist/components/error-boundary/index.js.map +1 -0
- package/dist/components/index.css +13 -10
- package/dist/components/index.css.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +47 -21
- package/dist/components/index.js.map +1 -1
- package/dist/components/knowledge-graph/edge-labels.d.ts.map +1 -1
- package/dist/components/knowledge-graph/index.js +18 -16
- package/dist/components/knowledge-graph/index.js.map +1 -1
- package/dist/components/label/index.js +5 -0
- package/dist/components/label/index.js.map +1 -0
- package/dist/components/label/label.d.ts.map +1 -1
- package/dist/components/loading-screen/index.js +4 -0
- package/dist/components/loading-screen/index.js.map +1 -0
- package/dist/components/map/MapPointPicker.d.ts.map +1 -1
- package/dist/components/map/index.js +2 -1
- package/dist/components/map/index.js.map +1 -1
- package/dist/components/navigation-progress/index.js +4 -0
- package/dist/components/navigation-progress/index.js.map +1 -0
- package/dist/components/page-content/index.js +4 -0
- package/dist/components/page-content/index.js.map +1 -0
- package/dist/components/popover/index.js +4 -0
- package/dist/components/popover/index.js.map +1 -0
- package/dist/components/research/diagram.d.ts.map +1 -1
- package/dist/components/research/index.js +6 -4
- package/dist/components/research/index.js.map +1 -1
- package/dist/components/research-editor/extensions.d.ts +1 -1
- package/dist/components/research-editor/index.js +11 -10
- package/dist/components/research-editor/index.js.map +1 -1
- package/dist/components/research-editor/math-navigation.d.ts +2 -2
- package/dist/components/research-editor/math-navigation.d.ts.map +1 -1
- package/dist/components/scroll-to-top/index.js +4 -0
- package/dist/components/scroll-to-top/index.js.map +1 -0
- package/dist/components/search-input/index.js +7 -0
- package/dist/components/search-input/index.js.map +1 -0
- package/dist/components/search-input/search-input.d.ts +3 -1
- package/dist/components/search-input/search-input.d.ts.map +1 -1
- package/dist/components/skeleton/index.js +4 -0
- package/dist/components/skeleton/index.js.map +1 -0
- package/dist/components/snackbar/index.js +6 -0
- package/dist/components/snackbar/index.js.map +1 -0
- package/dist/components/stepper/index.js +4 -0
- package/dist/components/stepper/index.js.map +1 -0
- package/dist/components/table/index.d.ts +1 -0
- package/dist/components/table/index.d.ts.map +1 -1
- package/dist/components/table/index.js +5 -0
- package/dist/components/table/index.js.map +1 -0
- package/dist/components/table/table-viewport.d.ts +13 -0
- package/dist/components/table/table-viewport.d.ts.map +1 -0
- package/dist/components/table/table.d.ts +3 -1
- package/dist/components/table/table.d.ts.map +1 -1
- package/dist/components/tabs/index.js +6 -0
- package/dist/components/tabs/index.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +12 -1
- package/dist/components/tabs/tabs.d.ts.map +1 -1
- package/dist/core/index.js +12 -10
- package/dist/core/index.js.map +1 -1
- package/dist/forms/index.js +2 -0
- package/dist/forms/index.js.map +1 -1
- package/dist/hooks/index.js +14 -12
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-config-from-query.d.ts +2 -0
- package/dist/hooks/use-config-from-query.d.ts.map +1 -1
- package/dist/hooks/use-image-dimensions.d.ts.map +1 -1
- package/dist/hooks/use-keyboard-shortcut.d.ts.map +1 -1
- package/dist/hooks/use-scroll-position.d.ts.map +1 -1
- package/dist/hooks/use-window-size.d.ts.map +1 -1
- package/dist/icons/context.d.ts.map +1 -1
- package/dist/icons/index.js +3 -2
- package/dist/icons/index.js.map +1 -1
- package/dist/index.css +13 -10
- package/dist/index.css.map +1 -1
- package/dist/index.js +57 -31
- package/dist/index.js.map +1 -1
- package/dist/internal/research-parser.js +3 -0
- package/dist/internal/research-parser.js.map +1 -0
- package/dist/layouts/core/header-section.d.ts +1 -0
- package/dist/layouts/core/header-section.d.ts.map +1 -1
- package/dist/layouts/dashboard/layout.d.ts +3 -1
- package/dist/layouts/dashboard/layout.d.ts.map +1 -1
- package/dist/layouts/dashboard/sidenav.d.ts.map +1 -1
- package/dist/layouts/index.js +9 -8
- package/dist/layouts/index.js.map +1 -1
- package/dist/netron/index.js +2 -1
- package/dist/netron/index.js.map +1 -1
- package/dist/registry/index.js +1 -1
- package/dist/state/create-store.d.ts.map +1 -1
- package/dist/state/index.js +3 -2
- package/dist/state/index.js.map +1 -1
- package/dist/state/settings-version.d.ts.map +1 -1
- package/dist/theme/components/Chip.d.ts.map +1 -1
- package/dist/theme/components/Dialog.d.ts.map +1 -1
- package/dist/theme/components/TextField.d.ts.map +1 -1
- package/dist/theme/components/index.d.ts.map +1 -1
- package/dist/theme/components/theme-utils.d.ts +2 -2
- package/dist/theme/components/theme-utils.d.ts.map +1 -1
- package/dist/theme/index.js +8 -6
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/palette/overrides.d.ts +1 -0
- package/dist/theme/palette/overrides.d.ts.map +1 -1
- package/dist/theme/semantic-surface.d.ts +8 -0
- package/dist/theme/semantic-surface.d.ts.map +1 -0
- package/dist/types/index.js +2 -2
- package/dist/ui/index.js +6 -5
- package/dist/ui/index.js.map +1 -1
- package/dist/utils/async-lock.d.ts.map +1 -1
- package/package.json +143 -37
- package/dist/chunk-472SOF76.js.map +0 -1
- package/dist/chunk-4Z5DE5GK.js.map +0 -1
- package/dist/chunk-52PQL67Q.js.map +0 -1
- package/dist/chunk-AD4W7HYC.js.map +0 -1
- package/dist/chunk-ADG4HZEP.js.map +0 -1
- package/dist/chunk-BJE2AKD4.js.map +0 -1
- package/dist/chunk-BRDWQVRT.js.map +0 -1
- package/dist/chunk-DRFNMZLG.js.map +0 -1
- package/dist/chunk-FF5RF32O.js.map +0 -1
- package/dist/chunk-FU52GL2E.js +0 -3
- package/dist/chunk-GMIE6III.js.map +0 -1
- package/dist/chunk-JSQTYDPG.js +0 -3
- package/dist/chunk-KQ67XB6T.js.map +0 -1
- package/dist/chunk-LSPFFEJT.js.map +0 -1
- package/dist/chunk-OKTLA23Q.js.map +0 -1
- package/dist/chunk-SNZK5X6F.js.map +0 -1
- package/dist/chunk-SU3LVQ7N.js.map +0 -1
- package/dist/chunk-XIXSSI3B.js.map +0 -1
|
@@ -0,0 +1,1271 @@
|
|
|
1
|
+
import { TableViewport, isRowActionTarget } from './chunk-2KG2NI73.js';
|
|
2
|
+
import { SearchInput } from './chunk-CT46KJOR.js';
|
|
3
|
+
import { FilterIcon, EmptyIcon } from './chunk-VQVVHMPG.js';
|
|
4
|
+
import { useCallback, useState, useMemo, useTransition, useRef, useEffect, Fragment as Fragment$1 } from 'react';
|
|
5
|
+
import Stack from '@mui/material/Stack';
|
|
6
|
+
import TextField2 from '@mui/material/TextField';
|
|
7
|
+
import Chip from '@mui/material/Chip';
|
|
8
|
+
import MenuItem from '@mui/material/MenuItem';
|
|
9
|
+
import Box2 from '@mui/material/Box';
|
|
10
|
+
import Button from '@mui/material/Button';
|
|
11
|
+
import Typography2 from '@mui/material/Typography';
|
|
12
|
+
import Badge from '@mui/material/Badge';
|
|
13
|
+
import { styled, alpha } from '@mui/material/styles';
|
|
14
|
+
import dayjs from 'dayjs';
|
|
15
|
+
import InputAdornment from '@mui/material/InputAdornment';
|
|
16
|
+
import IconButton from '@mui/material/IconButton';
|
|
17
|
+
import Dialog from '@mui/material/Dialog';
|
|
18
|
+
import DialogTitle from '@mui/material/DialogTitle';
|
|
19
|
+
import DialogActions from '@mui/material/DialogActions';
|
|
20
|
+
import DialogContent from '@mui/material/DialogContent';
|
|
21
|
+
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
22
|
+
import FormHelperText from '@mui/material/FormHelperText';
|
|
23
|
+
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
|
24
|
+
import { DateCalendar, dateCalendarClasses } from '@mui/x-date-pickers/DateCalendar';
|
|
25
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
26
|
+
import MuiTable from '@mui/material/Table';
|
|
27
|
+
import TableBody from '@mui/material/TableBody';
|
|
28
|
+
import TableCell from '@mui/material/TableCell';
|
|
29
|
+
import TableHead from '@mui/material/TableHead';
|
|
30
|
+
import TableRow from '@mui/material/TableRow';
|
|
31
|
+
import TableSortLabel from '@mui/material/TableSortLabel';
|
|
32
|
+
import TablePagination from '@mui/material/TablePagination';
|
|
33
|
+
import Paper from '@mui/material/Paper';
|
|
34
|
+
import Checkbox from '@mui/material/Checkbox';
|
|
35
|
+
import Skeleton from '@mui/material/Skeleton';
|
|
36
|
+
|
|
37
|
+
function DateRangePicker({
|
|
38
|
+
open,
|
|
39
|
+
error,
|
|
40
|
+
onClose,
|
|
41
|
+
onSubmit,
|
|
42
|
+
startDate,
|
|
43
|
+
endDate,
|
|
44
|
+
onChangeStartDate,
|
|
45
|
+
onChangeEndDate,
|
|
46
|
+
slotProps,
|
|
47
|
+
variant = "input",
|
|
48
|
+
title,
|
|
49
|
+
translations,
|
|
50
|
+
// Exclude hook props that shouldn't go to Dialog
|
|
51
|
+
selected: _selected,
|
|
52
|
+
label: _label,
|
|
53
|
+
shortLabel: _shortLabel,
|
|
54
|
+
onOpen: _onOpen,
|
|
55
|
+
onReset: _onReset,
|
|
56
|
+
setStartDate: _setStartDate,
|
|
57
|
+
setEndDate: _setEndDate,
|
|
58
|
+
...other
|
|
59
|
+
}) {
|
|
60
|
+
const txTitle = translations?.title ?? title ?? "Select date range";
|
|
61
|
+
const txStart = translations?.startDate ?? "Start date";
|
|
62
|
+
const txEnd = translations?.endDate ?? "End date";
|
|
63
|
+
const txErrorRange = translations?.errorRange ?? "End date cannot be earlier than start date";
|
|
64
|
+
const txCancel = translations?.cancel ?? "Cancel";
|
|
65
|
+
const txApply = translations?.apply ?? "Apply";
|
|
66
|
+
const mdUp = useMediaQuery((theme) => theme.breakpoints.up("md"));
|
|
67
|
+
const isCalendarView = mdUp && variant === "calendar";
|
|
68
|
+
const handleSubmit = useCallback(() => {
|
|
69
|
+
onClose({}, "backdropClick");
|
|
70
|
+
onSubmit?.();
|
|
71
|
+
}, [onClose, onSubmit]);
|
|
72
|
+
const handleClose = useCallback(() => {
|
|
73
|
+
onClose({}, "backdropClick");
|
|
74
|
+
}, [onClose]);
|
|
75
|
+
const dialogPaperSx = slotProps?.paper?.sx;
|
|
76
|
+
return /* @__PURE__ */ jsxs(
|
|
77
|
+
Dialog,
|
|
78
|
+
{
|
|
79
|
+
fullWidth: true,
|
|
80
|
+
open,
|
|
81
|
+
onClose,
|
|
82
|
+
maxWidth: isCalendarView ? false : "xs",
|
|
83
|
+
slotProps: {
|
|
84
|
+
...slotProps,
|
|
85
|
+
paper: {
|
|
86
|
+
...slotProps?.paper,
|
|
87
|
+
sx: [
|
|
88
|
+
{ ...isCalendarView && { maxWidth: 720 } },
|
|
89
|
+
...Array.isArray(dialogPaperSx) ? dialogPaperSx : dialogPaperSx ? [dialogPaperSx] : []
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
...other,
|
|
94
|
+
children: [
|
|
95
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: txTitle }),
|
|
96
|
+
/* @__PURE__ */ jsxs(
|
|
97
|
+
DialogContent,
|
|
98
|
+
{
|
|
99
|
+
sx: [
|
|
100
|
+
(theme) => ({
|
|
101
|
+
gap: 3,
|
|
102
|
+
display: "flex",
|
|
103
|
+
overflow: "unset",
|
|
104
|
+
flexDirection: isCalendarView ? "row" : "column",
|
|
105
|
+
[`& .${dateCalendarClasses.root}`]: {
|
|
106
|
+
borderRadius: 2,
|
|
107
|
+
border: `dashed 1px ${theme.palette.divider}`
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
],
|
|
111
|
+
children: [
|
|
112
|
+
isCalendarView ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
113
|
+
/* @__PURE__ */ jsx(DateCalendar, { value: startDate, onChange: onChangeStartDate }),
|
|
114
|
+
/* @__PURE__ */ jsx(DateCalendar, { value: endDate, onChange: onChangeEndDate })
|
|
115
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
116
|
+
/* @__PURE__ */ jsx(DatePicker, { label: txStart, value: startDate, onChange: onChangeStartDate }),
|
|
117
|
+
/* @__PURE__ */ jsx(DatePicker, { label: txEnd, value: endDate, onChange: onChangeEndDate })
|
|
118
|
+
] }),
|
|
119
|
+
error && /* @__PURE__ */ jsx(FormHelperText, { error: true, sx: { px: 2 }, children: txErrorRange })
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
),
|
|
123
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [
|
|
124
|
+
/* @__PURE__ */ jsx(Button, { variant: "outlined", color: "inherit", onClick: handleClose, children: txCancel }),
|
|
125
|
+
/* @__PURE__ */ jsx(Button, { disabled: error, variant: "contained", onClick: handleSubmit, children: txApply })
|
|
126
|
+
] })
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
function CalendarIcon() {
|
|
132
|
+
return /* @__PURE__ */ jsxs(
|
|
133
|
+
"svg",
|
|
134
|
+
{
|
|
135
|
+
width: "18",
|
|
136
|
+
height: "18",
|
|
137
|
+
viewBox: "0 0 24 24",
|
|
138
|
+
fill: "none",
|
|
139
|
+
stroke: "currentColor",
|
|
140
|
+
strokeWidth: "1.5",
|
|
141
|
+
strokeLinecap: "round",
|
|
142
|
+
strokeLinejoin: "round",
|
|
143
|
+
children: [
|
|
144
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
145
|
+
/* @__PURE__ */ jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
|
|
146
|
+
/* @__PURE__ */ jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
|
|
147
|
+
/* @__PURE__ */ jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
function ClearIcon() {
|
|
153
|
+
return /* @__PURE__ */ jsxs(
|
|
154
|
+
"svg",
|
|
155
|
+
{
|
|
156
|
+
width: "14",
|
|
157
|
+
height: "14",
|
|
158
|
+
viewBox: "0 0 24 24",
|
|
159
|
+
fill: "none",
|
|
160
|
+
stroke: "currentColor",
|
|
161
|
+
strokeWidth: "2",
|
|
162
|
+
strokeLinecap: "round",
|
|
163
|
+
strokeLinejoin: "round",
|
|
164
|
+
children: [
|
|
165
|
+
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
166
|
+
/* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
function toDayjs(value) {
|
|
172
|
+
if (!value) return null;
|
|
173
|
+
const d = dayjs(value);
|
|
174
|
+
return d.isValid() ? d : null;
|
|
175
|
+
}
|
|
176
|
+
function toIso(value) {
|
|
177
|
+
if (!value || !value.isValid()) return "";
|
|
178
|
+
return value.format("YYYY-MM-DD");
|
|
179
|
+
}
|
|
180
|
+
function formatLabel(start, end, fromPrefix, toPrefix) {
|
|
181
|
+
if (!start && !end) return "";
|
|
182
|
+
const s = toDayjs(start);
|
|
183
|
+
const e = toDayjs(end);
|
|
184
|
+
if (s && e) {
|
|
185
|
+
if (s.isSame(e, "day")) return e.format("DD MMM YYYY");
|
|
186
|
+
if (s.isSame(e, "month")) return `${s.format("DD")} \u2013 ${e.format("DD MMM YYYY")}`;
|
|
187
|
+
if (s.isSame(e, "year")) return `${s.format("DD MMM")} \u2013 ${e.format("DD MMM YYYY")}`;
|
|
188
|
+
return `${s.format("DD MMM YYYY")} \u2013 ${e.format("DD MMM YYYY")}`;
|
|
189
|
+
}
|
|
190
|
+
if (s) return `${fromPrefix} ${s.format("DD MMM YYYY")}`;
|
|
191
|
+
if (e) return `${toPrefix} ${e.format("DD MMM YYYY")}`;
|
|
192
|
+
return "";
|
|
193
|
+
}
|
|
194
|
+
function DateRangeInput({
|
|
195
|
+
label = "Date range",
|
|
196
|
+
startDate,
|
|
197
|
+
endDate,
|
|
198
|
+
onChange,
|
|
199
|
+
width = 220,
|
|
200
|
+
variant = "input",
|
|
201
|
+
size = "small",
|
|
202
|
+
translations,
|
|
203
|
+
pickerTranslations
|
|
204
|
+
}) {
|
|
205
|
+
const [open, setOpen] = useState(false);
|
|
206
|
+
const [tempStart, setTempStart] = useState(toDayjs(startDate));
|
|
207
|
+
const [tempEnd, setTempEnd] = useState(toDayjs(endDate));
|
|
208
|
+
const txPlaceholder = translations?.placeholder ?? "Select dates...";
|
|
209
|
+
const txFrom = translations?.from ?? "From";
|
|
210
|
+
const txTo = translations?.to ?? "To";
|
|
211
|
+
const txClear = translations?.clear ?? "Clear date range";
|
|
212
|
+
const displayLabel = useMemo(
|
|
213
|
+
() => formatLabel(startDate, endDate, txFrom, txTo),
|
|
214
|
+
[startDate, endDate, txFrom, txTo]
|
|
215
|
+
);
|
|
216
|
+
const hasValue = !!startDate || !!endDate;
|
|
217
|
+
const handleOpen = useCallback(() => {
|
|
218
|
+
setTempStart(toDayjs(startDate));
|
|
219
|
+
setTempEnd(toDayjs(endDate));
|
|
220
|
+
setOpen(true);
|
|
221
|
+
}, [startDate, endDate]);
|
|
222
|
+
const handleClose = useCallback(() => {
|
|
223
|
+
setOpen(false);
|
|
224
|
+
}, []);
|
|
225
|
+
const handleSubmit = useCallback(() => {
|
|
226
|
+
onChange(toIso(tempStart), toIso(tempEnd));
|
|
227
|
+
setOpen(false);
|
|
228
|
+
}, [tempStart, tempEnd, onChange]);
|
|
229
|
+
const handleClear = useCallback(
|
|
230
|
+
(e) => {
|
|
231
|
+
e.stopPropagation();
|
|
232
|
+
onChange("", "");
|
|
233
|
+
},
|
|
234
|
+
[onChange]
|
|
235
|
+
);
|
|
236
|
+
const error = !!(tempStart && tempEnd && tempStart.isAfter(tempEnd));
|
|
237
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
238
|
+
/* @__PURE__ */ jsx(
|
|
239
|
+
TextField2,
|
|
240
|
+
{
|
|
241
|
+
size,
|
|
242
|
+
label,
|
|
243
|
+
value: displayLabel,
|
|
244
|
+
placeholder: txPlaceholder,
|
|
245
|
+
onClick: handleOpen,
|
|
246
|
+
slotProps: {
|
|
247
|
+
input: {
|
|
248
|
+
readOnly: true,
|
|
249
|
+
sx: { cursor: "pointer" },
|
|
250
|
+
startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", sx: { color: "text.disabled" }, children: /* @__PURE__ */ jsx(CalendarIcon, {}) }),
|
|
251
|
+
...hasValue && {
|
|
252
|
+
endAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: handleClear, "aria-label": txClear, sx: { p: 0.25 }, children: /* @__PURE__ */ jsx(ClearIcon, {}) }) })
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
inputLabel: { shrink: true }
|
|
256
|
+
},
|
|
257
|
+
sx: {
|
|
258
|
+
minWidth: width,
|
|
259
|
+
"& .MuiOutlinedInput-root": { borderRadius: 1 },
|
|
260
|
+
"& .MuiInputBase-input": { cursor: "pointer" }
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
),
|
|
264
|
+
/* @__PURE__ */ jsx(
|
|
265
|
+
DateRangePicker,
|
|
266
|
+
{
|
|
267
|
+
open,
|
|
268
|
+
error,
|
|
269
|
+
onClose: handleClose,
|
|
270
|
+
onSubmit: handleSubmit,
|
|
271
|
+
startDate: tempStart,
|
|
272
|
+
endDate: tempEnd,
|
|
273
|
+
onChangeStartDate: setTempStart,
|
|
274
|
+
onChangeEndDate: setTempEnd,
|
|
275
|
+
variant,
|
|
276
|
+
translations: pickerTranslations,
|
|
277
|
+
selected: !!(tempStart && tempEnd),
|
|
278
|
+
label: "",
|
|
279
|
+
shortLabel: "",
|
|
280
|
+
onOpen: handleOpen,
|
|
281
|
+
onReset: () => {
|
|
282
|
+
setTempStart(null);
|
|
283
|
+
setTempEnd(null);
|
|
284
|
+
},
|
|
285
|
+
setStartDate: setTempStart,
|
|
286
|
+
setEndDate: setTempEnd
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
] });
|
|
290
|
+
}
|
|
291
|
+
function useDebounce(value, delay) {
|
|
292
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
293
|
+
useEffect(() => {
|
|
294
|
+
const timer = setTimeout(() => setDebouncedValue(value), delay);
|
|
295
|
+
return () => clearTimeout(timer);
|
|
296
|
+
}, [value, delay]);
|
|
297
|
+
return debouncedValue;
|
|
298
|
+
}
|
|
299
|
+
function isFilterActive(config, values) {
|
|
300
|
+
if (config.type === "date-range") return !!(values[`${config.key}From`] || values[`${config.key}To`]);
|
|
301
|
+
if (config.type === "number-range") {
|
|
302
|
+
return ["Min", "Max"].some((suffix) => {
|
|
303
|
+
const end = values[`${config.key}${suffix}`];
|
|
304
|
+
return end !== void 0 && end !== null && end !== "";
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
const value = values[config.key];
|
|
308
|
+
if (value === void 0 || value === null || value === "") return false;
|
|
309
|
+
if (Array.isArray(value) && value.length === 0) return false;
|
|
310
|
+
if (config.type === "boolean" && value === false) return false;
|
|
311
|
+
if (config.type === "select" && value === "") return false;
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
function FilterToolbar({
|
|
315
|
+
filters,
|
|
316
|
+
values,
|
|
317
|
+
onChange,
|
|
318
|
+
onReset,
|
|
319
|
+
total,
|
|
320
|
+
searchDebounce = 300,
|
|
321
|
+
compact = false,
|
|
322
|
+
sx,
|
|
323
|
+
resetLabel = "Reset",
|
|
324
|
+
resultsLabel
|
|
325
|
+
}) {
|
|
326
|
+
const [, startTransition] = useTransition();
|
|
327
|
+
const searchFilter = filters.find((f) => f.type === "search");
|
|
328
|
+
const [localSearch, setLocalSearch] = useState(values[searchFilter?.key ?? "search"] ?? "");
|
|
329
|
+
const debouncedSearch = useDebounce(localSearch, searchDebounce);
|
|
330
|
+
const prevDebouncedRef = useRef(debouncedSearch);
|
|
331
|
+
useEffect(() => {
|
|
332
|
+
if (debouncedSearch !== prevDebouncedRef.current) {
|
|
333
|
+
prevDebouncedRef.current = debouncedSearch;
|
|
334
|
+
const key = searchFilter?.key ?? "search";
|
|
335
|
+
startTransition(() => {
|
|
336
|
+
onChange({ ...values, [key]: debouncedSearch });
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}, [debouncedSearch, searchFilter?.key, onChange, values]);
|
|
340
|
+
const searchValue = values[searchFilter?.key ?? "search"] ?? "";
|
|
341
|
+
useEffect(() => {
|
|
342
|
+
if (searchValue === prevDebouncedRef.current) return;
|
|
343
|
+
prevDebouncedRef.current = searchValue;
|
|
344
|
+
setLocalSearch(searchValue);
|
|
345
|
+
}, [searchValue]);
|
|
346
|
+
const activeCount = useMemo(
|
|
347
|
+
() => filters.filter((f) => f.type !== "search" && isFilterActive(f, values)).length,
|
|
348
|
+
[filters, values]
|
|
349
|
+
);
|
|
350
|
+
const hasAnyActive = useMemo(
|
|
351
|
+
() => filters.some((f) => isFilterActive(f, f.type === "search" ? { [f.key]: localSearch } : values)),
|
|
352
|
+
[filters, values, localSearch]
|
|
353
|
+
);
|
|
354
|
+
const handleChange = useCallback(
|
|
355
|
+
(key, value) => {
|
|
356
|
+
startTransition(() => {
|
|
357
|
+
onChange({ ...values, [key]: value });
|
|
358
|
+
});
|
|
359
|
+
},
|
|
360
|
+
[onChange, values]
|
|
361
|
+
);
|
|
362
|
+
const handleReset = useCallback(() => {
|
|
363
|
+
setLocalSearch("");
|
|
364
|
+
if (onReset) {
|
|
365
|
+
onReset();
|
|
366
|
+
} else {
|
|
367
|
+
const resetValues = {};
|
|
368
|
+
for (const f of filters) {
|
|
369
|
+
if (f.type === "search") resetValues[f.key] = "";
|
|
370
|
+
else if (f.type === "multi-select") resetValues[f.key] = [];
|
|
371
|
+
else if (f.type === "boolean") resetValues[f.key] = false;
|
|
372
|
+
else if (f.type === "date-range") {
|
|
373
|
+
resetValues[`${f.key}From`] = "";
|
|
374
|
+
resetValues[`${f.key}To`] = "";
|
|
375
|
+
} else if (f.type === "number-range") {
|
|
376
|
+
resetValues[`${f.key}Min`] = "";
|
|
377
|
+
resetValues[`${f.key}Max`] = "";
|
|
378
|
+
} else {
|
|
379
|
+
resetValues[f.key] = "";
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
onChange(resetValues);
|
|
383
|
+
}
|
|
384
|
+
}, [onReset, onChange, filters]);
|
|
385
|
+
const renderFilter = useCallback(
|
|
386
|
+
(config) => {
|
|
387
|
+
const { key, type, label, placeholder, options } = config;
|
|
388
|
+
switch (type) {
|
|
389
|
+
case "search":
|
|
390
|
+
return /* @__PURE__ */ jsx(
|
|
391
|
+
SearchInput,
|
|
392
|
+
{
|
|
393
|
+
value: localSearch,
|
|
394
|
+
onChange: setLocalSearch,
|
|
395
|
+
placeholder: placeholder ?? "Search...",
|
|
396
|
+
"aria-label": label,
|
|
397
|
+
fullWidth: true
|
|
398
|
+
},
|
|
399
|
+
key
|
|
400
|
+
);
|
|
401
|
+
case "select":
|
|
402
|
+
return /* @__PURE__ */ jsxs(
|
|
403
|
+
TextField2,
|
|
404
|
+
{
|
|
405
|
+
select: true,
|
|
406
|
+
size: "small",
|
|
407
|
+
value: values[key] ?? "",
|
|
408
|
+
onChange: (e) => handleChange(key, e.target.value),
|
|
409
|
+
slotProps: { select: { displayEmpty: true, "aria-label": label } },
|
|
410
|
+
sx: {
|
|
411
|
+
minWidth: 0,
|
|
412
|
+
width: "100%",
|
|
413
|
+
"& .MuiOutlinedInput-root": { borderRadius: 1 }
|
|
414
|
+
},
|
|
415
|
+
children: [
|
|
416
|
+
/* @__PURE__ */ jsx(MenuItem, { value: "", children: /* @__PURE__ */ jsx(
|
|
417
|
+
Typography2,
|
|
418
|
+
{
|
|
419
|
+
variant: "body2",
|
|
420
|
+
sx: {
|
|
421
|
+
color: "text.secondary"
|
|
422
|
+
},
|
|
423
|
+
children: label
|
|
424
|
+
}
|
|
425
|
+
) }),
|
|
426
|
+
options?.map((opt) => /* @__PURE__ */ jsx(MenuItem, { value: opt.value, children: opt.label }, opt.value))
|
|
427
|
+
]
|
|
428
|
+
},
|
|
429
|
+
key
|
|
430
|
+
);
|
|
431
|
+
case "multi-select": {
|
|
432
|
+
const selectedValues = values[key] ?? [];
|
|
433
|
+
return /* @__PURE__ */ jsx(
|
|
434
|
+
TextField2,
|
|
435
|
+
{
|
|
436
|
+
select: true,
|
|
437
|
+
size: "small",
|
|
438
|
+
value: selectedValues,
|
|
439
|
+
onChange: (e) => handleChange(key, e.target.value),
|
|
440
|
+
slotProps: {
|
|
441
|
+
select: {
|
|
442
|
+
multiple: true,
|
|
443
|
+
displayEmpty: true,
|
|
444
|
+
// Same reason as the single select above: the label lives in
|
|
445
|
+
// `renderValue` as placeholder text, leaving the control
|
|
446
|
+
// without an accessible name.
|
|
447
|
+
"aria-label": label,
|
|
448
|
+
renderValue: (selected) => {
|
|
449
|
+
const sel = selected;
|
|
450
|
+
if (sel.length === 0) {
|
|
451
|
+
return /* @__PURE__ */ jsx(
|
|
452
|
+
Typography2,
|
|
453
|
+
{
|
|
454
|
+
variant: "body2",
|
|
455
|
+
sx: {
|
|
456
|
+
color: "text.secondary"
|
|
457
|
+
},
|
|
458
|
+
children: label
|
|
459
|
+
}
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
return /* @__PURE__ */ jsx(Stack, { direction: "row", spacing: 0.5, sx: { overflow: "hidden" }, children: sel.map((val) => {
|
|
463
|
+
const opt = options?.find((o) => o.value === val);
|
|
464
|
+
return /* @__PURE__ */ jsx(
|
|
465
|
+
Chip,
|
|
466
|
+
{
|
|
467
|
+
label: opt?.label ?? val,
|
|
468
|
+
size: "small",
|
|
469
|
+
sx: { height: 20, fontSize: "0.75rem" }
|
|
470
|
+
},
|
|
471
|
+
val
|
|
472
|
+
);
|
|
473
|
+
}) });
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
sx: {
|
|
478
|
+
minWidth: 0,
|
|
479
|
+
width: "100%",
|
|
480
|
+
"& .MuiOutlinedInput-root": { borderRadius: 1 }
|
|
481
|
+
},
|
|
482
|
+
children: options?.map((opt) => /* @__PURE__ */ jsx(MenuItem, { value: opt.value, children: opt.label }, opt.value))
|
|
483
|
+
},
|
|
484
|
+
key
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
case "date-range":
|
|
488
|
+
return /* @__PURE__ */ jsx(
|
|
489
|
+
DateRangeInput,
|
|
490
|
+
{
|
|
491
|
+
label,
|
|
492
|
+
startDate: values[`${key}From`] ?? "",
|
|
493
|
+
endDate: values[`${key}To`] ?? "",
|
|
494
|
+
onChange: (from, to) => {
|
|
495
|
+
startTransition(() => onChange({ ...values, [`${key}From`]: from, [`${key}To`]: to }));
|
|
496
|
+
},
|
|
497
|
+
width: "100%",
|
|
498
|
+
size: "small"
|
|
499
|
+
},
|
|
500
|
+
key
|
|
501
|
+
);
|
|
502
|
+
case "boolean":
|
|
503
|
+
return /* @__PURE__ */ jsx(
|
|
504
|
+
Chip,
|
|
505
|
+
{
|
|
506
|
+
label,
|
|
507
|
+
variant: values[key] ? "filled" : "outlined",
|
|
508
|
+
color: values[key] ? "primary" : "default",
|
|
509
|
+
onClick: () => handleChange(key, !values[key]),
|
|
510
|
+
size: "small",
|
|
511
|
+
sx: {
|
|
512
|
+
borderRadius: 1,
|
|
513
|
+
fontWeight: 500,
|
|
514
|
+
height: 32,
|
|
515
|
+
cursor: "pointer",
|
|
516
|
+
transition: (theme) => theme.transitions.create(["background-color", "color", "border-color"], {
|
|
517
|
+
duration: theme.transitions.duration.shorter
|
|
518
|
+
})
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
key
|
|
522
|
+
);
|
|
523
|
+
case "number-range":
|
|
524
|
+
return /* @__PURE__ */ jsxs(
|
|
525
|
+
Stack,
|
|
526
|
+
{
|
|
527
|
+
direction: "row",
|
|
528
|
+
spacing: 1,
|
|
529
|
+
sx: {
|
|
530
|
+
alignItems: "center"
|
|
531
|
+
},
|
|
532
|
+
children: [
|
|
533
|
+
/* @__PURE__ */ jsx(
|
|
534
|
+
TextField2,
|
|
535
|
+
{
|
|
536
|
+
type: "number",
|
|
537
|
+
size: "small",
|
|
538
|
+
label: `${label} min`,
|
|
539
|
+
value: values[`${key}Min`] ?? "",
|
|
540
|
+
onChange: (e) => handleChange(`${key}Min`, e.target.value),
|
|
541
|
+
sx: { flex: 1, minWidth: 0 }
|
|
542
|
+
}
|
|
543
|
+
),
|
|
544
|
+
/* @__PURE__ */ jsx(
|
|
545
|
+
Typography2,
|
|
546
|
+
{
|
|
547
|
+
variant: "body2",
|
|
548
|
+
sx: {
|
|
549
|
+
color: "text.disabled",
|
|
550
|
+
px: 0.5
|
|
551
|
+
},
|
|
552
|
+
children: "\u2014"
|
|
553
|
+
}
|
|
554
|
+
),
|
|
555
|
+
/* @__PURE__ */ jsx(
|
|
556
|
+
TextField2,
|
|
557
|
+
{
|
|
558
|
+
type: "number",
|
|
559
|
+
size: "small",
|
|
560
|
+
label: `${label} max`,
|
|
561
|
+
value: values[`${key}Max`] ?? "",
|
|
562
|
+
onChange: (e) => handleChange(`${key}Max`, e.target.value),
|
|
563
|
+
sx: { flex: 1, minWidth: 0 }
|
|
564
|
+
}
|
|
565
|
+
)
|
|
566
|
+
]
|
|
567
|
+
},
|
|
568
|
+
key
|
|
569
|
+
);
|
|
570
|
+
default:
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
[localSearch, values, handleChange, onChange]
|
|
575
|
+
);
|
|
576
|
+
return /* @__PURE__ */ jsxs(
|
|
577
|
+
Stack,
|
|
578
|
+
{
|
|
579
|
+
spacing: compact ? 0 : 1.5,
|
|
580
|
+
sx: {
|
|
581
|
+
p: 1.5,
|
|
582
|
+
minWidth: 0,
|
|
583
|
+
borderRadius: 1,
|
|
584
|
+
border: (theme) => `1px solid ${theme.palette.divider}`,
|
|
585
|
+
bgcolor: (theme) => alpha(theme.palette.background.default, 0.5),
|
|
586
|
+
...sx
|
|
587
|
+
},
|
|
588
|
+
children: [
|
|
589
|
+
/* @__PURE__ */ jsxs(
|
|
590
|
+
Stack,
|
|
591
|
+
{
|
|
592
|
+
direction: "row",
|
|
593
|
+
sx: {
|
|
594
|
+
alignItems: "center",
|
|
595
|
+
flexWrap: "wrap",
|
|
596
|
+
gap: 1.5
|
|
597
|
+
},
|
|
598
|
+
children: [
|
|
599
|
+
filters.map((filter) => /* @__PURE__ */ jsx(
|
|
600
|
+
Box2,
|
|
601
|
+
{
|
|
602
|
+
sx: {
|
|
603
|
+
flex: filter.type === "search" ? "1 1 220px" : "0 1 auto",
|
|
604
|
+
width: filter.width ?? (filter.type === "number-range" ? 260 : filter.type === "boolean" ? "auto" : 180),
|
|
605
|
+
minWidth: 0,
|
|
606
|
+
maxWidth: "100%",
|
|
607
|
+
"& > .MuiFormControl-root": { width: "100%", minWidth: 0 }
|
|
608
|
+
},
|
|
609
|
+
children: renderFilter(filter)
|
|
610
|
+
},
|
|
611
|
+
filter.key
|
|
612
|
+
)),
|
|
613
|
+
/* @__PURE__ */ jsxs(
|
|
614
|
+
Stack,
|
|
615
|
+
{
|
|
616
|
+
direction: "row",
|
|
617
|
+
spacing: 1,
|
|
618
|
+
sx: {
|
|
619
|
+
alignItems: "center",
|
|
620
|
+
ml: "auto"
|
|
621
|
+
},
|
|
622
|
+
children: [
|
|
623
|
+
activeCount > 0 && /* @__PURE__ */ jsx(Badge, { badgeContent: activeCount, color: "primary", sx: { "& .MuiBadge-badge": { fontSize: "0.65rem" } }, children: /* @__PURE__ */ jsx(Box2, { sx: { color: "text.secondary", display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx(FilterIcon, {}) }) }),
|
|
624
|
+
hasAnyActive && /* @__PURE__ */ jsx(
|
|
625
|
+
Button,
|
|
626
|
+
{
|
|
627
|
+
size: "small",
|
|
628
|
+
onClick: handleReset,
|
|
629
|
+
sx: {
|
|
630
|
+
minWidth: 0,
|
|
631
|
+
px: 1.5,
|
|
632
|
+
fontSize: "0.75rem",
|
|
633
|
+
fontWeight: 500,
|
|
634
|
+
color: "text.secondary",
|
|
635
|
+
"&:hover": { color: "text.primary" }
|
|
636
|
+
},
|
|
637
|
+
children: resetLabel
|
|
638
|
+
}
|
|
639
|
+
)
|
|
640
|
+
]
|
|
641
|
+
}
|
|
642
|
+
)
|
|
643
|
+
]
|
|
644
|
+
}
|
|
645
|
+
),
|
|
646
|
+
total !== void 0 && !compact && /* @__PURE__ */ jsx(
|
|
647
|
+
Typography2,
|
|
648
|
+
{
|
|
649
|
+
variant: "caption",
|
|
650
|
+
sx: {
|
|
651
|
+
color: "text.disabled",
|
|
652
|
+
mt: 0.5
|
|
653
|
+
},
|
|
654
|
+
children: resultsLabel ? resultsLabel(total) : `${total.toLocaleString()} result${total !== 1 ? "s" : ""}`
|
|
655
|
+
}
|
|
656
|
+
)
|
|
657
|
+
]
|
|
658
|
+
}
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
var StyledTableContainer = styled(Paper)(({ theme }) => ({
|
|
662
|
+
borderRadius: theme.shape.borderRadius,
|
|
663
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
664
|
+
overflow: "hidden",
|
|
665
|
+
minWidth: 0,
|
|
666
|
+
maxWidth: "100%"
|
|
667
|
+
}));
|
|
668
|
+
var StyledTableHead = styled(TableHead)(({ theme }) => ({
|
|
669
|
+
backgroundColor: alpha(theme.palette.grey[500], 0.08),
|
|
670
|
+
"& .MuiTableCell-head": {
|
|
671
|
+
fontWeight: 600,
|
|
672
|
+
fontSize: theme.typography.pxToRem(13),
|
|
673
|
+
color: theme.palette.text.secondary,
|
|
674
|
+
backgroundColor: theme.vars?.palette.background.paper ?? theme.palette.background.paper,
|
|
675
|
+
whiteSpace: "nowrap",
|
|
676
|
+
borderBottom: `1px solid ${theme.palette.divider}`
|
|
677
|
+
}
|
|
678
|
+
}));
|
|
679
|
+
var StyledTableRow = styled(TableRow)(({ theme }) => ({
|
|
680
|
+
transition: theme.transitions.create("background-color", {
|
|
681
|
+
duration: theme.transitions.duration.shortest
|
|
682
|
+
}),
|
|
683
|
+
// `:nth-child(even)` for zebra-striping — table rows are homogeneous
|
|
684
|
+
// siblings, so child-position is equivalent to of-type but doesn't
|
|
685
|
+
// assume the rendered tag never changes (e.g. a row replaced by a
|
|
686
|
+
// skeleton placeholder still alternates correctly).
|
|
687
|
+
"&:nth-child(even)": {
|
|
688
|
+
backgroundColor: alpha(theme.palette.grey[500], 0.02)
|
|
689
|
+
},
|
|
690
|
+
"&:hover": {
|
|
691
|
+
backgroundColor: alpha(theme.palette.primary.main, 0.04)
|
|
692
|
+
},
|
|
693
|
+
"& .MuiTableCell-body": {
|
|
694
|
+
borderBottom: `1px solid ${alpha(theme.palette.divider, 0.6)}`
|
|
695
|
+
}
|
|
696
|
+
}));
|
|
697
|
+
var EMPTY_SELECTION = /* @__PURE__ */ new Set();
|
|
698
|
+
function AdminDataTable({
|
|
699
|
+
columns,
|
|
700
|
+
data,
|
|
701
|
+
total,
|
|
702
|
+
loading = false,
|
|
703
|
+
loadingRows = 5,
|
|
704
|
+
page,
|
|
705
|
+
pageSize,
|
|
706
|
+
onPageChange,
|
|
707
|
+
onPageSizeChange,
|
|
708
|
+
sortBy,
|
|
709
|
+
sortOrder = "asc",
|
|
710
|
+
onSort,
|
|
711
|
+
emptyMessage = "No data found",
|
|
712
|
+
loadError = null,
|
|
713
|
+
loadErrorLabels,
|
|
714
|
+
rowKey,
|
|
715
|
+
onRowClick,
|
|
716
|
+
rowSx,
|
|
717
|
+
renderExpanded,
|
|
718
|
+
pageSizeOptions = [10, 25, 50, 100],
|
|
719
|
+
stickyHeader = false,
|
|
720
|
+
dense = false,
|
|
721
|
+
maxHeight,
|
|
722
|
+
minWidth,
|
|
723
|
+
scrollLabel,
|
|
724
|
+
paginationLabels,
|
|
725
|
+
sx,
|
|
726
|
+
selectable = false,
|
|
727
|
+
selectedKeys,
|
|
728
|
+
onSelectionChange,
|
|
729
|
+
bulkActions
|
|
730
|
+
}) {
|
|
731
|
+
const getRowKey = useCallback(
|
|
732
|
+
(row, index) => {
|
|
733
|
+
if (rowKey) return rowKey(row);
|
|
734
|
+
const record = row;
|
|
735
|
+
if (record["id"] !== void 0) return String(record["id"]);
|
|
736
|
+
if (selectable && process.env["NODE_ENV"] !== "production") {
|
|
737
|
+
console.error(
|
|
738
|
+
"[AdminDataTable] `selectable` is on but rows have no stable key: pass `rowKey`, or give each row an `id`. Index-based keys make the selection positional, so sorting or paging silently re-targets it."
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
return String(index);
|
|
742
|
+
},
|
|
743
|
+
[rowKey, selectable]
|
|
744
|
+
);
|
|
745
|
+
const selection = selectedKeys ?? EMPTY_SELECTION;
|
|
746
|
+
const pageRowKeys = useMemo(
|
|
747
|
+
() => selectable ? data.map((row, index) => getRowKey(row, index)) : [],
|
|
748
|
+
[selectable, data, getRowKey]
|
|
749
|
+
);
|
|
750
|
+
const allPageSelected = pageRowKeys.length > 0 && pageRowKeys.every((k) => selection.has(k));
|
|
751
|
+
const somePageSelected = !allPageSelected && pageRowKeys.some((k) => selection.has(k));
|
|
752
|
+
const toggleAllOnPage = useCallback(() => {
|
|
753
|
+
if (!onSelectionChange) return;
|
|
754
|
+
const next = new Set(selection);
|
|
755
|
+
if (allPageSelected) {
|
|
756
|
+
pageRowKeys.forEach((k) => next.delete(k));
|
|
757
|
+
} else {
|
|
758
|
+
pageRowKeys.forEach((k) => next.add(k));
|
|
759
|
+
}
|
|
760
|
+
onSelectionChange(next);
|
|
761
|
+
}, [onSelectionChange, selection, allPageSelected, pageRowKeys]);
|
|
762
|
+
const toggleRow = useCallback(
|
|
763
|
+
(key) => {
|
|
764
|
+
if (!onSelectionChange) return;
|
|
765
|
+
const next = new Set(selection);
|
|
766
|
+
if (next.has(key)) next.delete(key);
|
|
767
|
+
else next.add(key);
|
|
768
|
+
onSelectionChange(next);
|
|
769
|
+
},
|
|
770
|
+
[onSelectionChange, selection]
|
|
771
|
+
);
|
|
772
|
+
const handleSort = useCallback(
|
|
773
|
+
(columnKey) => {
|
|
774
|
+
onSort?.(columnKey);
|
|
775
|
+
},
|
|
776
|
+
[onSort]
|
|
777
|
+
);
|
|
778
|
+
const handlePageChange = useCallback(
|
|
779
|
+
(_, newPage) => {
|
|
780
|
+
onPageChange(newPage);
|
|
781
|
+
},
|
|
782
|
+
[onPageChange]
|
|
783
|
+
);
|
|
784
|
+
const handlePageSizeChange = useCallback(
|
|
785
|
+
(event) => {
|
|
786
|
+
onPageSizeChange?.(parseInt(event.target.value, 10));
|
|
787
|
+
onPageChange(0);
|
|
788
|
+
},
|
|
789
|
+
[onPageSizeChange, onPageChange]
|
|
790
|
+
);
|
|
791
|
+
const skeletonRowCount = Math.max(1, Math.min(pageSize, loadingRows));
|
|
792
|
+
const skeletonRows = useMemo(
|
|
793
|
+
() => Array.from({ length: skeletonRowCount }, (_, i) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
794
|
+
selectable && /* @__PURE__ */ jsx(TableCell, { padding: "checkbox", children: /* @__PURE__ */ jsx(Skeleton, { variant: "rectangular", width: 18, height: 18, sx: { borderRadius: 0.5 } }) }),
|
|
795
|
+
columns.map((col) => /* @__PURE__ */ jsx(TableCell, { align: col.align ?? "left", children: /* @__PURE__ */ jsx(
|
|
796
|
+
Skeleton,
|
|
797
|
+
{
|
|
798
|
+
variant: "text",
|
|
799
|
+
width: col.align === "right" ? "60%" : "80%",
|
|
800
|
+
sx: {
|
|
801
|
+
ml: col.align === "right" ? "auto" : 0,
|
|
802
|
+
borderRadius: 0.5
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
) }, col.key))
|
|
806
|
+
] }, `skeleton-${i}`)),
|
|
807
|
+
[skeletonRowCount, columns, selectable]
|
|
808
|
+
);
|
|
809
|
+
const showBulkBar = selectable && selection.size > 0 && !!bulkActions;
|
|
810
|
+
if (!loading && data.length === 0) {
|
|
811
|
+
return /* @__PURE__ */ jsxs(StyledTableContainer, { sx, children: [
|
|
812
|
+
/* @__PURE__ */ jsx(TableViewport, { label: scrollLabel, children: /* @__PURE__ */ jsx(MuiTable, { sx: { minWidth }, size: dense ? "small" : "medium", stickyHeader, children: /* @__PURE__ */ jsx(StyledTableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
813
|
+
selectable && /* @__PURE__ */ jsx(TableCell, { padding: "checkbox" }),
|
|
814
|
+
columns.map((col) => /* @__PURE__ */ jsx(
|
|
815
|
+
TableCell,
|
|
816
|
+
{
|
|
817
|
+
align: col.align ?? "left",
|
|
818
|
+
style: { width: col.width, minWidth: col.minWidth },
|
|
819
|
+
children: col.header
|
|
820
|
+
},
|
|
821
|
+
col.key
|
|
822
|
+
))
|
|
823
|
+
] }) }) }) }),
|
|
824
|
+
/* @__PURE__ */ jsxs(
|
|
825
|
+
Box2,
|
|
826
|
+
{
|
|
827
|
+
sx: {
|
|
828
|
+
py: 6,
|
|
829
|
+
px: 2,
|
|
830
|
+
textAlign: "center",
|
|
831
|
+
overflowWrap: "anywhere",
|
|
832
|
+
display: "flex",
|
|
833
|
+
flexDirection: "column",
|
|
834
|
+
alignItems: "center",
|
|
835
|
+
gap: 1.5
|
|
836
|
+
},
|
|
837
|
+
children: [
|
|
838
|
+
/* @__PURE__ */ jsx(EmptyIcon, {}),
|
|
839
|
+
/* @__PURE__ */ jsx(
|
|
840
|
+
Typography2,
|
|
841
|
+
{
|
|
842
|
+
variant: "body2",
|
|
843
|
+
sx: { color: loadError ? "text.secondary" : "text.disabled" },
|
|
844
|
+
children: loadError ? loadErrorLabels?.empty ?? "Could not load this data" : emptyMessage
|
|
845
|
+
}
|
|
846
|
+
),
|
|
847
|
+
loadError && /* @__PURE__ */ jsx(Typography2, { variant: "caption", sx: { color: "text.disabled", maxWidth: 420, textAlign: "center" }, children: loadError })
|
|
848
|
+
]
|
|
849
|
+
}
|
|
850
|
+
)
|
|
851
|
+
] });
|
|
852
|
+
}
|
|
853
|
+
return /* @__PURE__ */ jsxs(StyledTableContainer, { sx, children: [
|
|
854
|
+
loadError && /* @__PURE__ */ jsxs(
|
|
855
|
+
Box2,
|
|
856
|
+
{
|
|
857
|
+
role: "status",
|
|
858
|
+
sx: {
|
|
859
|
+
display: "flex",
|
|
860
|
+
alignItems: "center",
|
|
861
|
+
gap: 1,
|
|
862
|
+
px: 2,
|
|
863
|
+
py: 1,
|
|
864
|
+
borderBottom: 1,
|
|
865
|
+
borderColor: "divider",
|
|
866
|
+
bgcolor: (theme) => alpha(theme.palette.warning.main, 0.12)
|
|
867
|
+
},
|
|
868
|
+
children: [
|
|
869
|
+
/* @__PURE__ */ jsx(Typography2, { variant: "body2", sx: { color: "warning.dark", fontWeight: 600 }, children: loadErrorLabels?.partial ?? "Some of this data could not be loaded" }),
|
|
870
|
+
/* @__PURE__ */ jsx(Typography2, { variant: "caption", sx: { color: "text.secondary" }, children: loadError })
|
|
871
|
+
]
|
|
872
|
+
}
|
|
873
|
+
),
|
|
874
|
+
showBulkBar && /* @__PURE__ */ jsxs(
|
|
875
|
+
Stack,
|
|
876
|
+
{
|
|
877
|
+
direction: "row",
|
|
878
|
+
spacing: 2,
|
|
879
|
+
sx: {
|
|
880
|
+
alignItems: "center",
|
|
881
|
+
px: 2,
|
|
882
|
+
py: 1,
|
|
883
|
+
borderBottom: (theme) => `1px solid ${theme.palette.divider}`,
|
|
884
|
+
bgcolor: (theme) => alpha(theme.palette.primary.main, 0.06)
|
|
885
|
+
},
|
|
886
|
+
children: [
|
|
887
|
+
/* @__PURE__ */ jsxs(
|
|
888
|
+
Typography2,
|
|
889
|
+
{
|
|
890
|
+
variant: "body2",
|
|
891
|
+
sx: {
|
|
892
|
+
fontWeight: 600
|
|
893
|
+
},
|
|
894
|
+
children: [
|
|
895
|
+
selection.size,
|
|
896
|
+
" selected"
|
|
897
|
+
]
|
|
898
|
+
}
|
|
899
|
+
),
|
|
900
|
+
/* @__PURE__ */ jsx(Box2, { sx: { flex: 1 } }),
|
|
901
|
+
bulkActions(selection)
|
|
902
|
+
]
|
|
903
|
+
}
|
|
904
|
+
),
|
|
905
|
+
/* @__PURE__ */ jsx(TableViewport, { label: scrollLabel, maxHeight, children: /* @__PURE__ */ jsxs(MuiTable, { sx: { minWidth }, size: dense ? "small" : "medium", stickyHeader, children: [
|
|
906
|
+
/* @__PURE__ */ jsx(StyledTableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
907
|
+
selectable && /* @__PURE__ */ jsx(TableCell, { padding: "checkbox", children: /* @__PURE__ */ jsx(
|
|
908
|
+
Checkbox,
|
|
909
|
+
{
|
|
910
|
+
size: "small",
|
|
911
|
+
indeterminate: somePageSelected,
|
|
912
|
+
checked: allPageSelected,
|
|
913
|
+
disabled: loading || pageRowKeys.length === 0,
|
|
914
|
+
onChange: toggleAllOnPage,
|
|
915
|
+
slotProps: {
|
|
916
|
+
input: { "aria-label": "select all rows on page" }
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
) }),
|
|
920
|
+
columns.map((col) => /* @__PURE__ */ jsx(
|
|
921
|
+
TableCell,
|
|
922
|
+
{
|
|
923
|
+
align: col.align ?? "left",
|
|
924
|
+
style: { width: col.width, minWidth: col.minWidth },
|
|
925
|
+
sortDirection: sortBy === col.key ? sortOrder : false,
|
|
926
|
+
children: col.sortable && onSort ? /* @__PURE__ */ jsx(
|
|
927
|
+
TableSortLabel,
|
|
928
|
+
{
|
|
929
|
+
active: sortBy === col.key,
|
|
930
|
+
direction: sortBy === col.key ? sortOrder : "asc",
|
|
931
|
+
onClick: () => handleSort(col.key),
|
|
932
|
+
children: col.header
|
|
933
|
+
}
|
|
934
|
+
) : col.header
|
|
935
|
+
},
|
|
936
|
+
col.key
|
|
937
|
+
))
|
|
938
|
+
] }) }),
|
|
939
|
+
/* @__PURE__ */ jsx(TableBody, { children: loading ? skeletonRows : data.map((row, index) => {
|
|
940
|
+
const key = getRowKey(row, index);
|
|
941
|
+
const isSelected = selectable && selection.has(key);
|
|
942
|
+
const body = /* @__PURE__ */ jsxs(
|
|
943
|
+
StyledTableRow,
|
|
944
|
+
{
|
|
945
|
+
hover: true,
|
|
946
|
+
selected: isSelected,
|
|
947
|
+
tabIndex: onRowClick || selectable ? -1 : void 0,
|
|
948
|
+
"data-row-action": onRowClick ? true : void 0,
|
|
949
|
+
onClick: onRowClick ? (event) => {
|
|
950
|
+
if (isRowActionTarget(event.target)) onRowClick(row);
|
|
951
|
+
} : void 0,
|
|
952
|
+
sx: {
|
|
953
|
+
cursor: onRowClick ? "pointer" : "default",
|
|
954
|
+
"&:focus-visible": { outline: "2px solid", outlineColor: "primary.main", outlineOffset: -2 },
|
|
955
|
+
...rowSx?.(row, index)
|
|
956
|
+
},
|
|
957
|
+
children: [
|
|
958
|
+
selectable && /* @__PURE__ */ jsx(
|
|
959
|
+
TableCell,
|
|
960
|
+
{
|
|
961
|
+
padding: "checkbox",
|
|
962
|
+
onClick: (e) => e.stopPropagation(),
|
|
963
|
+
children: /* @__PURE__ */ jsx(
|
|
964
|
+
Checkbox,
|
|
965
|
+
{
|
|
966
|
+
size: "small",
|
|
967
|
+
checked: isSelected,
|
|
968
|
+
onChange: () => toggleRow(key),
|
|
969
|
+
slotProps: {
|
|
970
|
+
input: { "aria-label": "select row" }
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
)
|
|
974
|
+
}
|
|
975
|
+
),
|
|
976
|
+
columns.map((col) => /* @__PURE__ */ jsx(TableCell, { align: col.align ?? "left", children: col.render(row, index) }, col.key))
|
|
977
|
+
]
|
|
978
|
+
},
|
|
979
|
+
key
|
|
980
|
+
);
|
|
981
|
+
const detail = renderExpanded?.(row, index);
|
|
982
|
+
if (detail == null) return body;
|
|
983
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
984
|
+
body,
|
|
985
|
+
/* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length + (selectable ? 1 : 0), sx: { py: 0, borderBottom: 0 }, children: detail }) })
|
|
986
|
+
] }, `${key}-group`);
|
|
987
|
+
}) })
|
|
988
|
+
] }) }),
|
|
989
|
+
/* @__PURE__ */ jsx(
|
|
990
|
+
TablePagination,
|
|
991
|
+
{
|
|
992
|
+
component: "div",
|
|
993
|
+
count: total,
|
|
994
|
+
page,
|
|
995
|
+
rowsPerPage: pageSize,
|
|
996
|
+
rowsPerPageOptions: pageSizeOptions,
|
|
997
|
+
onPageChange: handlePageChange,
|
|
998
|
+
onRowsPerPageChange: handlePageSizeChange,
|
|
999
|
+
...paginationLabels?.rowsPerPage != null && { labelRowsPerPage: paginationLabels.rowsPerPage },
|
|
1000
|
+
...paginationLabels?.displayedRows != null && { labelDisplayedRows: paginationLabels.displayedRows },
|
|
1001
|
+
sx: {
|
|
1002
|
+
borderTop: (theme) => `1px solid ${theme.palette.divider}`,
|
|
1003
|
+
"& .MuiTablePagination-displayedRows": {
|
|
1004
|
+
fontSize: "0.8rem"
|
|
1005
|
+
},
|
|
1006
|
+
"& .MuiTablePagination-selectLabel": {
|
|
1007
|
+
fontSize: "0.8rem"
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
)
|
|
1012
|
+
] });
|
|
1013
|
+
}
|
|
1014
|
+
var DEFAULT_COLOR_MAP = {
|
|
1015
|
+
active: "success",
|
|
1016
|
+
completed: "success",
|
|
1017
|
+
confirmed: "success",
|
|
1018
|
+
approved: "success",
|
|
1019
|
+
enabled: "success",
|
|
1020
|
+
online: "success",
|
|
1021
|
+
paid: "success",
|
|
1022
|
+
resolved: "success",
|
|
1023
|
+
success: "success",
|
|
1024
|
+
pending: "warning",
|
|
1025
|
+
processing: "warning",
|
|
1026
|
+
waiting: "warning",
|
|
1027
|
+
review: "warning",
|
|
1028
|
+
draft: "warning",
|
|
1029
|
+
failed: "error",
|
|
1030
|
+
error: "error",
|
|
1031
|
+
rejected: "error",
|
|
1032
|
+
blocked: "error",
|
|
1033
|
+
banned: "error",
|
|
1034
|
+
disabled: "error",
|
|
1035
|
+
cancelled: "error",
|
|
1036
|
+
expired: "error",
|
|
1037
|
+
suspended: "error",
|
|
1038
|
+
offline: "error",
|
|
1039
|
+
info: "info",
|
|
1040
|
+
new: "info",
|
|
1041
|
+
open: "info"
|
|
1042
|
+
};
|
|
1043
|
+
function StatusChip({ status, label, colorMap, size = "small", sx, ref, ...other }) {
|
|
1044
|
+
const normalizedStatus = status.toLowerCase();
|
|
1045
|
+
const mergedMap = colorMap ? { ...DEFAULT_COLOR_MAP, ...colorMap } : DEFAULT_COLOR_MAP;
|
|
1046
|
+
const mapped = Object.hasOwn(mergedMap, normalizedStatus) ? mergedMap[normalizedStatus] : void 0;
|
|
1047
|
+
const color = mapped ?? "default";
|
|
1048
|
+
const displayLabel = label ?? status.charAt(0).toUpperCase() + status.slice(1).toLowerCase();
|
|
1049
|
+
return /* @__PURE__ */ jsx(
|
|
1050
|
+
Chip,
|
|
1051
|
+
{
|
|
1052
|
+
ref,
|
|
1053
|
+
...other,
|
|
1054
|
+
label: displayLabel,
|
|
1055
|
+
size,
|
|
1056
|
+
sx: [
|
|
1057
|
+
{
|
|
1058
|
+
height: size === "small" ? 22 : 28,
|
|
1059
|
+
fontSize: size === "small" ? "0.7rem" : "0.775rem",
|
|
1060
|
+
fontWeight: 600,
|
|
1061
|
+
borderRadius: 0.75,
|
|
1062
|
+
letterSpacing: "0.01em",
|
|
1063
|
+
...color !== "default" && {
|
|
1064
|
+
color: (theme) => theme.palette[color].main,
|
|
1065
|
+
bgcolor: (theme) => alpha(theme.palette[color].main, 0.1),
|
|
1066
|
+
border: (theme) => `1px solid ${alpha(theme.palette[color].main, 0.2)}`
|
|
1067
|
+
},
|
|
1068
|
+
...color === "default" && {
|
|
1069
|
+
color: "text.secondary",
|
|
1070
|
+
bgcolor: (theme) => alpha(theme.palette.grey[500], 0.08),
|
|
1071
|
+
border: (theme) => `1px solid ${alpha(theme.palette.grey[500], 0.16)}`
|
|
1072
|
+
}
|
|
1073
|
+
},
|
|
1074
|
+
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
1075
|
+
]
|
|
1076
|
+
}
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// src/utils/format-crypto.ts
|
|
1081
|
+
var COIN_DISPLAY_DECIMALS = Object.freeze(
|
|
1082
|
+
// Prototype-free: a plain literal answers `COIN_DISPLAY_DECIMALS['constructor']`
|
|
1083
|
+
// with a function, which `?? FALLBACK_DECIMALS` accepts as a precision. That
|
|
1084
|
+
// produced `toFixed(NaN)` — silently formatting with zero decimals instead
|
|
1085
|
+
// of eight, for any coin code that collides with an Object.prototype key.
|
|
1086
|
+
Object.assign(/* @__PURE__ */ Object.create(null), { btc: 8, xmr: 8 })
|
|
1087
|
+
);
|
|
1088
|
+
var COIN_WIRE_DECIMALS = Object.freeze(
|
|
1089
|
+
Object.assign(/* @__PURE__ */ Object.create(null), { btc: 8, xmr: 12 })
|
|
1090
|
+
);
|
|
1091
|
+
var FALLBACK_DECIMALS = 8;
|
|
1092
|
+
var FALLBACK_WIRE_DECIMALS = 12;
|
|
1093
|
+
var DECIMAL = /^([+-]?)(\d*)(?:\.(\d*))?$/;
|
|
1094
|
+
function getCoinDecimals(coin) {
|
|
1095
|
+
const decimals = COIN_DISPLAY_DECIMALS[coin.toLowerCase()];
|
|
1096
|
+
return typeof decimals === "number" ? decimals : FALLBACK_DECIMALS;
|
|
1097
|
+
}
|
|
1098
|
+
function getCoinWireDecimals(coin) {
|
|
1099
|
+
const decimals = COIN_WIRE_DECIMALS[coin.toLowerCase()];
|
|
1100
|
+
return typeof decimals === "number" ? decimals : FALLBACK_WIRE_DECIMALS;
|
|
1101
|
+
}
|
|
1102
|
+
function formatDecimalString(raw, decimals, rounding = "down") {
|
|
1103
|
+
const scaled = toScaledInteger(raw, decimals, rounding);
|
|
1104
|
+
return scaled === null ? null : fromScaledInteger(scaled, decimals);
|
|
1105
|
+
}
|
|
1106
|
+
function toScaledInteger(raw, decimals, rounding = "half-up") {
|
|
1107
|
+
const match = DECIMAL.exec(raw.trim());
|
|
1108
|
+
if (!match) return null;
|
|
1109
|
+
const [, sign = "", intPart = "", fracPart = ""] = match;
|
|
1110
|
+
if (intPart === "" && fracPart === "") return null;
|
|
1111
|
+
const digits = `${intPart || "0"}${fracPart.slice(0, decimals).padEnd(decimals, "0")}`;
|
|
1112
|
+
const roundUp = rounding === "half-up" && (fracPart[decimals] ?? "0") >= "5";
|
|
1113
|
+
const magnitude = BigInt(digits) + (roundUp ? 1n : 0n);
|
|
1114
|
+
return sign === "-" ? -magnitude : magnitude;
|
|
1115
|
+
}
|
|
1116
|
+
function fromScaledInteger(scaled, decimals) {
|
|
1117
|
+
const negative = scaled < 0n;
|
|
1118
|
+
const asString = (negative ? -scaled : scaled).toString().padStart(decimals + 1, "0");
|
|
1119
|
+
const whole = asString.slice(0, asString.length - decimals) || "0";
|
|
1120
|
+
const fraction = decimals > 0 ? asString.slice(asString.length - decimals) : "";
|
|
1121
|
+
const magnitude = decimals > 0 ? `${whole}.${fraction}` : whole;
|
|
1122
|
+
return `${negative && scaled !== 0n ? "-" : ""}${magnitude}`;
|
|
1123
|
+
}
|
|
1124
|
+
function isNonZeroDecimal(raw) {
|
|
1125
|
+
const match = DECIMAL.exec(raw.trim());
|
|
1126
|
+
if (!match) return false;
|
|
1127
|
+
const [, , intPart = "", fracPart = ""] = match;
|
|
1128
|
+
if (intPart === "" && fracPart === "") return false;
|
|
1129
|
+
return /[1-9]/.test(intPart) || /[1-9]/.test(fracPart);
|
|
1130
|
+
}
|
|
1131
|
+
function sumDecimalStrings(values, decimals, options) {
|
|
1132
|
+
const rounding = options?.rounding ?? "half-up";
|
|
1133
|
+
let total = 0n;
|
|
1134
|
+
for (const value of values) {
|
|
1135
|
+
if (value === null || value === void 0 || value === "") continue;
|
|
1136
|
+
const scaled = toScaledInteger(
|
|
1137
|
+
typeof value === "number" ? String(value) : value,
|
|
1138
|
+
decimals,
|
|
1139
|
+
rounding
|
|
1140
|
+
);
|
|
1141
|
+
if (scaled !== null) total += scaled;
|
|
1142
|
+
}
|
|
1143
|
+
return fromScaledInteger(total, decimals);
|
|
1144
|
+
}
|
|
1145
|
+
function subtractDecimalStrings(minuend, subtrahends, decimals, options) {
|
|
1146
|
+
if (minuend === null || minuend === void 0 || minuend === "") return null;
|
|
1147
|
+
const rounding = options?.rounding ?? "half-up";
|
|
1148
|
+
let total = toScaledInteger(
|
|
1149
|
+
typeof minuend === "number" ? String(minuend) : minuend,
|
|
1150
|
+
decimals,
|
|
1151
|
+
rounding
|
|
1152
|
+
);
|
|
1153
|
+
if (total === null) return null;
|
|
1154
|
+
for (const value of subtrahends) {
|
|
1155
|
+
if (value === null || value === void 0 || value === "") continue;
|
|
1156
|
+
const scaled = toScaledInteger(
|
|
1157
|
+
typeof value === "number" ? String(value) : value,
|
|
1158
|
+
decimals,
|
|
1159
|
+
rounding
|
|
1160
|
+
);
|
|
1161
|
+
if (scaled !== null) total -= scaled;
|
|
1162
|
+
}
|
|
1163
|
+
if (options?.clampAtZero && total < 0n) total = 0n;
|
|
1164
|
+
return fromScaledInteger(total, decimals);
|
|
1165
|
+
}
|
|
1166
|
+
function formatCoinAmount(value, coin, options) {
|
|
1167
|
+
const code = coin.toLowerCase();
|
|
1168
|
+
const symbol = options?.symbol ?? coin.toUpperCase();
|
|
1169
|
+
const withSymbol = options?.withSymbol !== false;
|
|
1170
|
+
const decimals = Math.max(0, options?.precision ?? getCoinDecimals(code));
|
|
1171
|
+
const trim = options?.trim === true;
|
|
1172
|
+
const rounding = options?.rounding ?? "down";
|
|
1173
|
+
const markDust = options?.markDust !== false;
|
|
1174
|
+
const raw = typeof value === "string" ? value.trim() : typeof value === "number" && Number.isFinite(value) ? String(Object.is(value, -0) ? 0 : value) : "";
|
|
1175
|
+
let formatted = raw === "" ? null : formatDecimalString(raw, decimals, rounding);
|
|
1176
|
+
const exact = formatted !== null;
|
|
1177
|
+
if (formatted === null) {
|
|
1178
|
+
let n = typeof value === "number" ? value : Number(raw);
|
|
1179
|
+
if (!Number.isFinite(n)) n = 0;
|
|
1180
|
+
if (Object.is(n, -0)) n = 0;
|
|
1181
|
+
formatted = n.toFixed(decimals);
|
|
1182
|
+
}
|
|
1183
|
+
if (markDust && exact && !/[1-9]/.test(formatted) && isNonZeroDecimal(raw)) {
|
|
1184
|
+
const epsilon = fromScaledInteger(1n, decimals);
|
|
1185
|
+
const below = raw.startsWith("-");
|
|
1186
|
+
return withSymbol ? `${below ? ">" : "<"} ${below ? "-" : ""}${epsilon} ${symbol}` : `${below ? ">" : "<"} ${below ? "-" : ""}${epsilon}`;
|
|
1187
|
+
}
|
|
1188
|
+
if (trim && formatted.includes(".")) {
|
|
1189
|
+
formatted = formatted.replace(/\.?0+$/, "");
|
|
1190
|
+
if (formatted === "" || formatted === "-") formatted = "0";
|
|
1191
|
+
}
|
|
1192
|
+
return withSymbol ? `${formatted} ${symbol}` : formatted;
|
|
1193
|
+
}
|
|
1194
|
+
function formatCoinAmountList(totals, options) {
|
|
1195
|
+
const sep = options?.separator ?? " \xB7 ";
|
|
1196
|
+
return Object.keys(totals).sort().map((coin) => formatCoinAmount(totals[coin], coin, options)).join(sep);
|
|
1197
|
+
}
|
|
1198
|
+
function formatAmount(amount, decimals) {
|
|
1199
|
+
const num = parseFloat(amount);
|
|
1200
|
+
if (Number.isNaN(num)) return amount;
|
|
1201
|
+
const scaled = decimals !== void 0 ? formatDecimalString(amount, decimals) : null;
|
|
1202
|
+
const fixed = scaled ?? (decimals !== void 0 ? num.toFixed(decimals) : amount);
|
|
1203
|
+
const [intPart, decPart] = fixed.split(".");
|
|
1204
|
+
const absInt = intPart.replace("-", "");
|
|
1205
|
+
const formatted = absInt.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
1206
|
+
const prefix = num < 0 ? "-" : "";
|
|
1207
|
+
return decPart !== void 0 ? `${prefix}${formatted}.${decPart}` : `${prefix}${formatted}`;
|
|
1208
|
+
}
|
|
1209
|
+
function AmountCell({
|
|
1210
|
+
amount,
|
|
1211
|
+
currency,
|
|
1212
|
+
decimals,
|
|
1213
|
+
showSign = false,
|
|
1214
|
+
color = false,
|
|
1215
|
+
sx
|
|
1216
|
+
}) {
|
|
1217
|
+
const num = parseFloat(amount);
|
|
1218
|
+
const isNegative = num < 0;
|
|
1219
|
+
const isPositive = num > 0;
|
|
1220
|
+
const formatted = useMemo(() => formatAmount(amount, decimals), [amount, decimals]);
|
|
1221
|
+
const signPrefix = useMemo(() => {
|
|
1222
|
+
if (!showSign) return "";
|
|
1223
|
+
if (isPositive) return "+";
|
|
1224
|
+
return "";
|
|
1225
|
+
}, [showSign, isPositive]);
|
|
1226
|
+
const textColor = useMemo(() => {
|
|
1227
|
+
if (!color) return void 0;
|
|
1228
|
+
if (isPositive) return "success.main";
|
|
1229
|
+
if (isNegative) return "error.main";
|
|
1230
|
+
return "text.secondary";
|
|
1231
|
+
}, [color, isPositive, isNegative]);
|
|
1232
|
+
return /* @__PURE__ */ jsxs(
|
|
1233
|
+
Typography2,
|
|
1234
|
+
{
|
|
1235
|
+
variant: "body2",
|
|
1236
|
+
color: textColor,
|
|
1237
|
+
sx: {
|
|
1238
|
+
fontFamily: '"JetBrains Mono", "Fira Code", "SF Mono", "Consolas", monospace',
|
|
1239
|
+
fontVariantNumeric: "tabular-nums",
|
|
1240
|
+
fontSize: "0.8rem",
|
|
1241
|
+
fontWeight: 500,
|
|
1242
|
+
whiteSpace: "nowrap",
|
|
1243
|
+
textAlign: "right",
|
|
1244
|
+
...sx
|
|
1245
|
+
},
|
|
1246
|
+
children: [
|
|
1247
|
+
signPrefix,
|
|
1248
|
+
formatted,
|
|
1249
|
+
currency && /* @__PURE__ */ jsx(
|
|
1250
|
+
Typography2,
|
|
1251
|
+
{
|
|
1252
|
+
component: "span",
|
|
1253
|
+
variant: "caption",
|
|
1254
|
+
sx: {
|
|
1255
|
+
color: "text.disabled",
|
|
1256
|
+
ml: 0.5,
|
|
1257
|
+
fontFamily: "inherit",
|
|
1258
|
+
fontSize: "0.7rem",
|
|
1259
|
+
fontWeight: 400
|
|
1260
|
+
},
|
|
1261
|
+
children: currency
|
|
1262
|
+
}
|
|
1263
|
+
)
|
|
1264
|
+
]
|
|
1265
|
+
}
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
export { AdminDataTable, AmountCell, COIN_DISPLAY_DECIMALS, COIN_WIRE_DECIMALS, DateRangeInput, DateRangePicker, FilterToolbar, StatusChip, formatCoinAmount, formatCoinAmountList, formatDecimalString, fromScaledInteger, getCoinDecimals, getCoinWireDecimals, subtractDecimalStrings, sumDecimalStrings, toScaledInteger };
|
|
1270
|
+
//# sourceMappingURL=chunk-F6RZ7LW6.js.map
|
|
1271
|
+
//# sourceMappingURL=chunk-F6RZ7LW6.js.map
|