@campxdev/react-blueprint 1.7.2 → 1.7.4
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/export.ts +1 -0
- package/package.json +1 -1
- package/src/assets/export.ts +2 -0
- package/src/assets/fonts/export.ts +2 -0
- package/src/assets/images/export.ts +2 -0
- package/src/assets/images/gif/index.ts +1 -1
- package/src/assets/images/svg/index.ts +12 -12
- package/src/components/Assets/ErrorPages/InternalServerError.tsx +5 -5
- package/src/components/Assets/ErrorPages/NoInternetConnection.tsx +5 -5
- package/src/components/Assets/ErrorPages/NoItemFound.tsx +6 -5
- package/src/components/Assets/ErrorPages/PageNotFound.tsx +5 -5
- package/src/components/Assets/ErrorPages/UnAuthorized.tsx +5 -5
- package/src/components/Assets/ErrorPages/styles.tsx +1 -1
- package/src/components/Assets/Icons/IconComponents/CautionIcon.tsx +37 -0
- package/src/components/Assets/Icons/IconComponents/ClearIcon.tsx +37 -0
- package/src/components/Assets/Icons/IconComponents/DoneSquare.tsx +2 -2
- package/src/components/Assets/Icons/IconComponents/DownArrow.tsx +32 -0
- package/src/components/Assets/Icons/IconComponents/LIneDivider.tsx +23 -0
- package/src/components/Assets/Icons/IconComponents/PrintDesignerIcon.tsx +47 -0
- package/src/components/Assets/Icons/IconComponents/RedirectIcon.tsx +15 -7
- package/src/components/Assets/Icons/IconComponents/SettlementsIcon.tsx +53 -0
- package/src/components/Assets/Icons/Icons.tsx +12 -0
- package/src/components/DataDisplay/ActivityLogView/ActivityLogView.tsx +2 -2
- package/src/components/DataDisplay/ActivityLogView/service.tsx +1 -19
- package/src/components/DataDisplay/DataTable/DataTable.tsx +62 -39
- package/src/components/DataDisplay/DataTable/TablePagination.tsx +20 -12
- package/src/components/DataDisplay/EmptyIllustration/EmptyIllustration.tsx +40 -0
- package/src/components/DataDisplay/export.ts +1 -0
- package/src/components/Feedback/Alert/Alert.tsx +2 -3
- package/src/components/Feedback/Spinner/Spinner.css +13 -25
- package/src/components/Input/RadioGroup/RadioGroup.tsx +6 -2
- package/src/components/Input/SearchBar/SearchBar.tsx +17 -14
- package/src/components/Input/SingleSelect/SingleSelect.tsx +2 -1
- package/src/components/Input/SingleSelect/components/MenuFooter.tsx +24 -0
- package/src/components/Input/SingleSelect/components/OptionsLoader.tsx +14 -0
- package/src/components/Input/SingleSelect/components/SingleFilter.tsx +69 -62
- package/src/components/Input/SingleSelect/components/SingleInput.tsx +45 -18
- package/src/components/Input/TextField/TextField.tsx +4 -1
- package/src/components/Input/styles.tsx +5 -5
- package/src/components/Layout/PageContent/PageContent.tsx +4 -3
- package/src/components/Layout/PageHeader/PageHeader.tsx +22 -69
- package/src/components/Layout/PageHeader/components/SearchBar.tsx +69 -26
- package/src/components/Layout/PageHeader/components/TableColumnsSelector/TableColumnsSelector.tsx +125 -23
- package/src/components/Navigation/Breadcrumbs/Breadcrumbs.tsx +1 -0
- package/src/components/Navigation/ConfirmDialog/ConfirmDialog.tsx +3 -3
- package/src/components/Navigation/DropDownMenu/DropDownMenu.tsx +2 -2
- package/src/components/Navigation/PreviewFiles/PreviewFiles.tsx +56 -81
- package/src/components/Navigation/Sidebar/styles.tsx +2 -1
- package/src/components/Navigation/TabsContainer/TabsContainer.tsx +1 -1
- package/src/components/Navigation/UploadDialog/LoadingUploadDialogContainer.tsx +3 -3
- package/src/components/Navigation/UploadDialog/UploadDialog.tsx +46 -33
- package/src/components/Navigation/UploadDialog/UploadDialogContainer.tsx +2 -2
- package/src/redux/slices/pageHeaderSlice.ts +4 -1
- package/src/stories/Navigation/PreviewFiles.stories.tsx +43 -9
- package/src/themes/commonTheme.ts +30 -5
- package/src/themes/customCssBaseline.ts +3 -2
- package/src/components/DataDisplay/styles.tsx +0 -6
- package/src/components/Input/components/OptionsLoader.tsx +0 -22
- /package/src/assets/images/svg/{Emptylistmage.svg → empty.svg} +0 -0
- /package/src/assets/images/svg/{error-cactus.svg → error-image.svg} +0 -0
- /package/src/assets/images/svg/{Internalserverimage.svg → server-error.svg} +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AutocompleteCloseReason,
|
|
3
3
|
Box,
|
|
4
|
+
InputAdornment,
|
|
4
5
|
Autocomplete as MuiAutocomplete,
|
|
5
6
|
Paper,
|
|
6
7
|
} from '@mui/material';
|
|
7
8
|
import { debounce, startCase } from 'lodash';
|
|
8
9
|
import { SyntheticEvent, useMemo } from 'react';
|
|
9
10
|
import { Typography } from '../../../DataDisplay/Typography/Typography';
|
|
10
|
-
import { SingleSelectProps, Spinner } from '../../../export';
|
|
11
|
+
import { Icons, SingleSelectProps, Spinner } from '../../../export';
|
|
11
12
|
import { TextField } from '../../TextField/TextField';
|
|
12
|
-
import { OptionsLoader } from '../../components/OptionsLoader';
|
|
13
|
-
import { OptionContainer } from '../../styles';
|
|
14
13
|
import { SingleSelectState } from '../singleSelectReducer';
|
|
14
|
+
import { OptionsLoader } from './OptionsLoader';
|
|
15
15
|
|
|
16
16
|
declare module '@mui/material/Autocomplete' {
|
|
17
17
|
interface AutocompletePaperSlotPropsOverrides {
|
|
@@ -29,7 +29,7 @@ const CustomPaper = (props: any) => (
|
|
|
29
29
|
}}
|
|
30
30
|
>
|
|
31
31
|
{props.children}
|
|
32
|
-
|
|
32
|
+
{props.loadingOptions ? <OptionsLoader isSearch={props.isSearch} /> : <></>}
|
|
33
33
|
</Paper>
|
|
34
34
|
);
|
|
35
35
|
|
|
@@ -62,6 +62,7 @@ export const SingleInput = ({
|
|
|
62
62
|
handleClose,
|
|
63
63
|
handleScroll,
|
|
64
64
|
state,
|
|
65
|
+
disableClear = false,
|
|
65
66
|
...restProps
|
|
66
67
|
}: SingleInputProps) => {
|
|
67
68
|
const {
|
|
@@ -98,15 +99,18 @@ export const SingleInput = ({
|
|
|
98
99
|
/>
|
|
99
100
|
);
|
|
100
101
|
}
|
|
102
|
+
|
|
101
103
|
return (
|
|
102
104
|
<MuiAutocomplete
|
|
103
105
|
{...restProps}
|
|
106
|
+
disableClearable
|
|
107
|
+
forcePopupIcon={false}
|
|
104
108
|
onChange={(e, value) => {
|
|
105
109
|
onChange(getValue ? getValue(value) : value?.value);
|
|
106
110
|
}}
|
|
107
111
|
onInputCapture={handleSearch}
|
|
108
112
|
open={open}
|
|
109
|
-
autoFocus={
|
|
113
|
+
autoFocus={false}
|
|
110
114
|
filterOptions={(options, state) => {
|
|
111
115
|
if (optionsApiEndPoint) {
|
|
112
116
|
return options;
|
|
@@ -119,19 +123,17 @@ export const SingleInput = ({
|
|
|
119
123
|
PaperComponent={CustomPaper}
|
|
120
124
|
renderOption={(props, option: any) => {
|
|
121
125
|
return (
|
|
122
|
-
<Box component="li" {...props} key={option.value}>
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
</Typography>
|
|
134
|
-
</OptionContainer>
|
|
126
|
+
<Box component="li" {...props} margin="4px 0px" key={option.value}>
|
|
127
|
+
<Typography variant="subtitle3">
|
|
128
|
+
{dbLabelProps.useLabelStartCase
|
|
129
|
+
? startCase(option.label)
|
|
130
|
+
: option.label}
|
|
131
|
+
</Typography>
|
|
132
|
+
<Typography variant="caption">
|
|
133
|
+
{dbLabelProps.useSubLabelStartCase
|
|
134
|
+
? startCase(option?.subLabel)
|
|
135
|
+
: option?.subLabel}
|
|
136
|
+
</Typography>
|
|
135
137
|
</Box>
|
|
136
138
|
);
|
|
137
139
|
}}
|
|
@@ -158,6 +160,31 @@ export const SingleInput = ({
|
|
|
158
160
|
name={name}
|
|
159
161
|
error={error}
|
|
160
162
|
helperText={helperText}
|
|
163
|
+
fullWidth
|
|
164
|
+
slotProps={{
|
|
165
|
+
input: {
|
|
166
|
+
...params.InputProps,
|
|
167
|
+
sx: {
|
|
168
|
+
paddingRight: '18px',
|
|
169
|
+
},
|
|
170
|
+
endAdornment: (
|
|
171
|
+
<InputAdornment position="end">
|
|
172
|
+
<Icons.DownArrow
|
|
173
|
+
disabled={params.disabled}
|
|
174
|
+
onClick={
|
|
175
|
+
params.disabled
|
|
176
|
+
? () => {}
|
|
177
|
+
: open
|
|
178
|
+
? (e) => {
|
|
179
|
+
handleClose(e, 'escape');
|
|
180
|
+
}
|
|
181
|
+
: handleOpen
|
|
182
|
+
}
|
|
183
|
+
/>
|
|
184
|
+
</InputAdornment>
|
|
185
|
+
),
|
|
186
|
+
},
|
|
187
|
+
}}
|
|
161
188
|
/>
|
|
162
189
|
)}
|
|
163
190
|
/>
|
|
@@ -26,7 +26,10 @@ export const TextField = ({
|
|
|
26
26
|
label={label}
|
|
27
27
|
required={required}
|
|
28
28
|
name={name}
|
|
29
|
-
containerProps={
|
|
29
|
+
containerProps={{
|
|
30
|
+
...(rest.fullWidth && { width: '100%' }),
|
|
31
|
+
...containerProps,
|
|
32
|
+
}}
|
|
30
33
|
>
|
|
31
34
|
<MuiTextField
|
|
32
35
|
required={required}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Box, Stack, styled } from '@mui/material';
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const FilterOptionContainer = styled(Box)(({ theme }) => ({
|
|
4
4
|
display: 'flex',
|
|
5
5
|
flexDirection: 'column',
|
|
6
6
|
borderBottom: `1px solid ${theme.palette.secondary.main}`,
|
|
7
7
|
width: '100%',
|
|
8
|
-
padding: '4px 0px',
|
|
9
8
|
}));
|
|
10
9
|
|
|
11
|
-
export const
|
|
12
|
-
backgroundColor: theme.palette.
|
|
13
|
-
|
|
10
|
+
export const FooterContainer = styled(Stack)(({ theme }) => ({
|
|
11
|
+
backgroundColor: theme.palette.surface.defaultBackground,
|
|
12
|
+
borderRadius: '4px',
|
|
13
|
+
height: '40px',
|
|
14
14
|
}));
|
|
@@ -4,8 +4,7 @@ const PageContentContainer = styled(Box)(({ theme }) => ({
|
|
|
4
4
|
display: 'flex',
|
|
5
5
|
flexDirection: 'column',
|
|
6
6
|
overflowY: 'auto',
|
|
7
|
-
padding: '
|
|
8
|
-
gap: '16px',
|
|
7
|
+
padding: '12px',
|
|
9
8
|
backgroundColor: theme.palette.surface.paperBackground,
|
|
10
9
|
height: 'calc(100vh - 148px)',
|
|
11
10
|
width: '100%',
|
|
@@ -14,6 +13,8 @@ const PageContentContainer = styled(Box)(({ theme }) => ({
|
|
|
14
13
|
|
|
15
14
|
export const PageContent = (props: BoxProps) => {
|
|
16
15
|
return (
|
|
17
|
-
<PageContentContainer {...props}>
|
|
16
|
+
<PageContentContainer gap="12px" {...props}>
|
|
17
|
+
{props.children}
|
|
18
|
+
</PageContentContainer>
|
|
18
19
|
);
|
|
19
20
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, Divider, Stack, useTheme } from '@mui/material';
|
|
2
2
|
import { GridColDef } from '@mui/x-data-grid';
|
|
3
|
-
import {
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
4
|
import {
|
|
5
5
|
cloneElement,
|
|
6
6
|
Fragment,
|
|
@@ -8,19 +8,16 @@ import {
|
|
|
8
8
|
ReactNode,
|
|
9
9
|
useState,
|
|
10
10
|
} from 'react';
|
|
11
|
-
import { useDispatch } from 'react-redux';
|
|
11
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
12
12
|
import { setFilterByNameForUniqueId } from '../../../redux/slices/pageHeaderSlice';
|
|
13
|
+
import { RootState } from '../../../redux/store';
|
|
13
14
|
import {
|
|
14
15
|
DensitySelector,
|
|
15
16
|
Icons,
|
|
16
17
|
TableColumnsSelector,
|
|
17
18
|
Typography,
|
|
18
19
|
} from '../../export';
|
|
19
|
-
import {
|
|
20
|
-
ColumnsAnchor,
|
|
21
|
-
FiltersAnchor,
|
|
22
|
-
SearchAnchor,
|
|
23
|
-
} from './components/Anchors';
|
|
20
|
+
import { FiltersAnchor } from './components/Anchors';
|
|
24
21
|
import { SearchBar } from './components/SearchBar';
|
|
25
22
|
|
|
26
23
|
interface PageHeaderProps {
|
|
@@ -36,7 +33,7 @@ const ViewTab = ({ title }: { title: string }) => {
|
|
|
36
33
|
const theme = useTheme();
|
|
37
34
|
return (
|
|
38
35
|
<Stack>
|
|
39
|
-
<Stack direction="row" gap={1} alignItems="center" padding="8px">
|
|
36
|
+
<Stack direction="row" gap={1} alignItems="center" padding="8px 0px">
|
|
40
37
|
<Icons.ViewsIcon />
|
|
41
38
|
<Typography variant="subtitle3">{title}</Typography>
|
|
42
39
|
</Stack>
|
|
@@ -54,7 +51,7 @@ const ViewTab = ({ title }: { title: string }) => {
|
|
|
54
51
|
|
|
55
52
|
const motionDivVariants = {
|
|
56
53
|
collapsed: { height: '48px' },
|
|
57
|
-
expanded: { height: '
|
|
54
|
+
expanded: { height: '108px' },
|
|
58
55
|
};
|
|
59
56
|
|
|
60
57
|
export const PageHeader = ({
|
|
@@ -66,7 +63,7 @@ export const PageHeader = ({
|
|
|
66
63
|
searchText = 'Search',
|
|
67
64
|
}: PageHeaderProps) => {
|
|
68
65
|
const [expanded, setExpanded] = useState(false);
|
|
69
|
-
|
|
66
|
+
|
|
70
67
|
const dispatch = useDispatch();
|
|
71
68
|
|
|
72
69
|
const wrapProps = (element: ReactElement): ReactElement => {
|
|
@@ -89,13 +86,17 @@ export const PageHeader = ({
|
|
|
89
86
|
|
|
90
87
|
const theme = useTheme();
|
|
91
88
|
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
const filters = useSelector((state: RootState) =>
|
|
90
|
+
uniqueId ? state.pageHeader[uniqueId]?.filters : undefined,
|
|
91
|
+
);
|
|
95
92
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
const hasFilters =
|
|
94
|
+
!!filters &&
|
|
95
|
+
Object.entries(filters).some(([key, value]) => {
|
|
96
|
+
return (
|
|
97
|
+
!['search', 'limit', 'offset', 'skip'].includes(key) && value !== null
|
|
98
|
+
);
|
|
99
|
+
});
|
|
99
100
|
|
|
100
101
|
const isTableMode = columns && uniqueId;
|
|
101
102
|
|
|
@@ -104,10 +105,8 @@ export const PageHeader = ({
|
|
|
104
105
|
style={{
|
|
105
106
|
display: 'flex',
|
|
106
107
|
flexDirection: 'column',
|
|
107
|
-
gap: '10px',
|
|
108
|
-
margin: '8px 0px',
|
|
109
|
-
padding: '0px 16px',
|
|
110
108
|
height: '48px',
|
|
109
|
+
gap: '8px',
|
|
111
110
|
}}
|
|
112
111
|
variants={motionDivVariants}
|
|
113
112
|
animate={expanded ? 'expanded' : 'collapsed'}
|
|
@@ -118,6 +117,7 @@ export const PageHeader = ({
|
|
|
118
117
|
width="100%"
|
|
119
118
|
alignItems="center"
|
|
120
119
|
justifyContent="space-between"
|
|
120
|
+
height="48px"
|
|
121
121
|
>
|
|
122
122
|
{isTableMode ? <ViewTab title="Default View" /> : viewsSlot}
|
|
123
123
|
|
|
@@ -127,48 +127,14 @@ export const PageHeader = ({
|
|
|
127
127
|
handleClick={() => {
|
|
128
128
|
setExpanded(!expanded);
|
|
129
129
|
}}
|
|
130
|
-
showDot={
|
|
130
|
+
showDot={hasFilters}
|
|
131
131
|
/>
|
|
132
132
|
)}
|
|
133
133
|
{isTableMode && (
|
|
134
|
-
<
|
|
135
|
-
handleClick={() => {
|
|
136
|
-
setExpanded(!expanded);
|
|
137
|
-
}}
|
|
138
|
-
showDot={false}
|
|
139
|
-
/>
|
|
134
|
+
<TableColumnsSelector columns={columns} uniqueId={uniqueId} />
|
|
140
135
|
)}
|
|
141
136
|
{isTableMode && (
|
|
142
|
-
<
|
|
143
|
-
{expandedSearch ? (
|
|
144
|
-
<motion.div
|
|
145
|
-
key="searchBar"
|
|
146
|
-
initial={{ opacity: 0, x: -20, scale: 0.95 }}
|
|
147
|
-
animate={{ opacity: 1, x: 0, scale: 1 }}
|
|
148
|
-
exit={{ opacity: 0, x: 20, scale: 0.95 }}
|
|
149
|
-
transition={{ duration: 0.3 }}
|
|
150
|
-
>
|
|
151
|
-
<SearchBar
|
|
152
|
-
searchText={searchText}
|
|
153
|
-
handleSearchBlur={handleSearchBlur}
|
|
154
|
-
uniqueId={uniqueId}
|
|
155
|
-
/>
|
|
156
|
-
</motion.div>
|
|
157
|
-
) : (
|
|
158
|
-
<motion.div
|
|
159
|
-
key="searchAnchor"
|
|
160
|
-
initial={{ opacity: 0, x: 20, scale: 0.95 }}
|
|
161
|
-
animate={{ opacity: 1, x: 0, scale: 1 }}
|
|
162
|
-
exit={{ opacity: 0, x: -20, scale: 0.95 }}
|
|
163
|
-
transition={{ duration: 0.3 }}
|
|
164
|
-
>
|
|
165
|
-
<SearchAnchor
|
|
166
|
-
handleClick={handleSearchClick}
|
|
167
|
-
showDot={false}
|
|
168
|
-
/>
|
|
169
|
-
</motion.div>
|
|
170
|
-
)}
|
|
171
|
-
</AnimatePresence>
|
|
137
|
+
<SearchBar searchText={searchText} uniqueId={uniqueId} />
|
|
172
138
|
)}
|
|
173
139
|
{isTableMode && <DensitySelector uniqueId={uniqueId} />}
|
|
174
140
|
{actions.map((action, index) => action)}
|
|
@@ -183,18 +149,6 @@ export const PageHeader = ({
|
|
|
183
149
|
)}
|
|
184
150
|
{expanded && (
|
|
185
151
|
<Stack direction="row" width="100%" alignItems="center" gap={2}>
|
|
186
|
-
{isTableMode && (
|
|
187
|
-
<>
|
|
188
|
-
<TableColumnsSelector columns={columns} uniqueId={uniqueId} />
|
|
189
|
-
<Divider
|
|
190
|
-
orientation="vertical"
|
|
191
|
-
style={{
|
|
192
|
-
height: '20px',
|
|
193
|
-
background: theme.palette.border.primary,
|
|
194
|
-
}}
|
|
195
|
-
/>
|
|
196
|
-
</>
|
|
197
|
-
)}
|
|
198
152
|
{filterComponents.map((filter, index) => (
|
|
199
153
|
<Fragment key={index}>
|
|
200
154
|
{wrapProps(filter)}
|
|
@@ -209,7 +163,6 @@ export const PageHeader = ({
|
|
|
209
163
|
)}
|
|
210
164
|
</Fragment>
|
|
211
165
|
))}
|
|
212
|
-
<Stack direction="row"></Stack>
|
|
213
166
|
</Stack>
|
|
214
167
|
)}
|
|
215
168
|
</motion.div>
|
|
@@ -1,28 +1,34 @@
|
|
|
1
|
-
import { InputAdornment } from '@mui/material';
|
|
1
|
+
import { InputAdornment, Stack } from '@mui/material';
|
|
2
|
+
import { AnimatePresence, motion } from 'framer-motion';
|
|
2
3
|
import { debounce } from 'lodash';
|
|
3
|
-
import React, { useMemo } from 'react';
|
|
4
|
+
import React, { useMemo, useState } from 'react';
|
|
4
5
|
import { useDispatch, useSelector } from 'react-redux';
|
|
5
6
|
import { setSearchForUniqueId } from '../../../../redux/slices/pageHeaderSlice';
|
|
6
7
|
import { RootState } from '../../../../redux/store';
|
|
7
8
|
import { Icons, TextField } from '../../../export';
|
|
9
|
+
import { SearchAnchor } from './Anchors';
|
|
8
10
|
|
|
9
11
|
export const SearchBar = ({
|
|
10
|
-
handleSearchBlur,
|
|
11
12
|
uniqueId,
|
|
12
13
|
searchText,
|
|
13
14
|
}: {
|
|
14
|
-
handleSearchBlur: () => void;
|
|
15
15
|
uniqueId: string;
|
|
16
16
|
searchText: string;
|
|
17
17
|
}) => {
|
|
18
18
|
const dispatch = useDispatch();
|
|
19
19
|
|
|
20
|
+
const [expandedSearch, setExpandedSearch] = useState(false);
|
|
21
|
+
|
|
22
|
+
const handleSearchClick = () => {
|
|
23
|
+
setExpandedSearch(true);
|
|
24
|
+
};
|
|
25
|
+
|
|
20
26
|
const search = useSelector(
|
|
21
27
|
(state: RootState) => state.pageHeader[uniqueId]?.filters?.search,
|
|
22
28
|
);
|
|
23
29
|
|
|
24
30
|
// Wrap onSearch in useCallback
|
|
25
|
-
const onSearch = (value: string) => {
|
|
31
|
+
const onSearch = (value: string | null) => {
|
|
26
32
|
dispatch(
|
|
27
33
|
setSearchForUniqueId({
|
|
28
34
|
uniqueId: uniqueId,
|
|
@@ -31,36 +37,73 @@ export const SearchBar = ({
|
|
|
31
37
|
);
|
|
32
38
|
};
|
|
33
39
|
|
|
34
|
-
// Now we can memoize a debounced version of onSearch
|
|
35
40
|
const debouncedSendRequest = useMemo(
|
|
36
41
|
() => debounce(onSearch, 300),
|
|
37
42
|
[onSearch],
|
|
38
43
|
);
|
|
39
44
|
|
|
40
|
-
// Pass the updated value to the debounced function in onChange
|
|
41
45
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
42
46
|
debouncedSendRequest(e.target.value);
|
|
43
47
|
};
|
|
44
48
|
|
|
49
|
+
const handleClearClick = (e: any) => {
|
|
50
|
+
onSearch(null);
|
|
51
|
+
setExpandedSearch(false);
|
|
52
|
+
};
|
|
53
|
+
|
|
45
54
|
return (
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
<AnimatePresence mode="wait">
|
|
56
|
+
{expandedSearch ? (
|
|
57
|
+
<motion.div
|
|
58
|
+
key="searchBar"
|
|
59
|
+
initial={{ opacity: 0, x: -20, scale: 0.95 }}
|
|
60
|
+
animate={{ opacity: 1, x: 0, scale: 1 }}
|
|
61
|
+
exit={{ opacity: 0, x: 20, scale: 0.95 }}
|
|
62
|
+
transition={{ duration: 0.3 }}
|
|
63
|
+
>
|
|
64
|
+
<TextField
|
|
65
|
+
containerProps={{
|
|
66
|
+
margin: '0px',
|
|
67
|
+
width: '300px',
|
|
68
|
+
}}
|
|
69
|
+
sx={{
|
|
70
|
+
input: {
|
|
71
|
+
padding: '9px 9px 9px 4px',
|
|
72
|
+
},
|
|
73
|
+
}}
|
|
74
|
+
size="small"
|
|
75
|
+
placeholder={searchText}
|
|
76
|
+
defaultValue={search || ''}
|
|
77
|
+
onChange={handleChange}
|
|
78
|
+
InputProps={{
|
|
79
|
+
startAdornment: (
|
|
80
|
+
// <InputAdornment position="start">
|
|
81
|
+
<Stack direction="row" alignItems="center" gap="4px">
|
|
82
|
+
<Icons.SearchIcon />
|
|
83
|
+
<Icons.LineDividerIcon />
|
|
84
|
+
</Stack>
|
|
85
|
+
// </InputAdornment>
|
|
86
|
+
),
|
|
87
|
+
endAdornment: (
|
|
88
|
+
<InputAdornment position="end">
|
|
89
|
+
<Icons.ClearIcon onClick={handleClearClick} />
|
|
90
|
+
</InputAdornment>
|
|
91
|
+
),
|
|
92
|
+
}}
|
|
93
|
+
autoFocus
|
|
94
|
+
/>
|
|
95
|
+
</motion.div>
|
|
96
|
+
) : (
|
|
97
|
+
<motion.div
|
|
98
|
+
key="searchAnchor"
|
|
99
|
+
initial={{ opacity: 0, x: 20, scale: 0.95 }}
|
|
100
|
+
animate={{ opacity: 1, x: 0, scale: 1 }}
|
|
101
|
+
exit={{ opacity: 0, x: -20, scale: 0.95 }}
|
|
102
|
+
transition={{ duration: 0.3 }}
|
|
103
|
+
>
|
|
104
|
+
<SearchAnchor handleClick={handleSearchClick} showDot={false} />
|
|
105
|
+
</motion.div>
|
|
106
|
+
)}
|
|
107
|
+
</AnimatePresence>
|
|
65
108
|
);
|
|
66
109
|
};
|
package/src/components/Layout/PageHeader/components/TableColumnsSelector/TableColumnsSelector.tsx
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
MenuListProps,
|
|
3
|
+
MenuProps,
|
|
4
|
+
Stack,
|
|
5
|
+
styled,
|
|
6
|
+
Typography,
|
|
7
|
+
useTheme,
|
|
8
|
+
} from '@mui/material';
|
|
3
9
|
import { GridColDef, GridColumnVisibilityModel } from '@mui/x-data-grid';
|
|
4
10
|
import { useState } from 'react';
|
|
5
11
|
import { useDispatch, useSelector } from 'react-redux';
|
|
6
12
|
import { setColumnVisibilityModelForUniqueId } from '../../../../../redux/slices/pageHeaderSlice';
|
|
7
13
|
import { RootState } from '../../../../../redux/store';
|
|
8
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
Button,
|
|
16
|
+
EmptyIllustration,
|
|
17
|
+
Icons,
|
|
18
|
+
SearchBar,
|
|
19
|
+
SingleCheckBox,
|
|
20
|
+
} from '../../../../export';
|
|
9
21
|
import { DropdownMenu } from '../../../../Navigation/export';
|
|
22
|
+
import { ColumnsAnchor } from '../Anchors';
|
|
10
23
|
|
|
11
24
|
export type TableColumnsSelectorProps = {
|
|
12
25
|
columns: GridColDef[];
|
|
@@ -15,6 +28,37 @@ export type TableColumnsSelectorProps = {
|
|
|
15
28
|
uniqueId: string;
|
|
16
29
|
};
|
|
17
30
|
|
|
31
|
+
export const FooterContainerContainer = styled(Stack)(({ theme }) => ({
|
|
32
|
+
backgroundColor: theme.palette.surface.defaultBackground,
|
|
33
|
+
borderRadius: '4px',
|
|
34
|
+
height: '40px',
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
export const TableColumnsSelectorMenuFooter = ({
|
|
38
|
+
onClick,
|
|
39
|
+
}: {
|
|
40
|
+
onClick: () => void;
|
|
41
|
+
}) => {
|
|
42
|
+
const theme = useTheme();
|
|
43
|
+
return (
|
|
44
|
+
<FooterContainerContainer direction="row" alignItems="center">
|
|
45
|
+
<Button
|
|
46
|
+
variant="text"
|
|
47
|
+
onClick={onClick}
|
|
48
|
+
sx={{
|
|
49
|
+
fontFamily: 'Heebo',
|
|
50
|
+
minWidth: '0px',
|
|
51
|
+
margin: '0px 16px',
|
|
52
|
+
}}
|
|
53
|
+
disableRipple
|
|
54
|
+
color={theme.palette.text.tertiary}
|
|
55
|
+
>
|
|
56
|
+
Reset
|
|
57
|
+
</Button>
|
|
58
|
+
</FooterContainerContainer>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
18
62
|
export const TableColumnsSelector = ({
|
|
19
63
|
columns,
|
|
20
64
|
uniqueId,
|
|
@@ -36,7 +80,7 @@ export const TableColumnsSelector = ({
|
|
|
36
80
|
const theme = useTheme();
|
|
37
81
|
|
|
38
82
|
const filteredOptions = columns.filter((option) =>
|
|
39
|
-
option.
|
|
83
|
+
option.headerName?.toLowerCase().includes(search.toLowerCase()),
|
|
40
84
|
);
|
|
41
85
|
|
|
42
86
|
const handleCheckboxChange = (column: GridColDef, checked: boolean) => {
|
|
@@ -56,26 +100,16 @@ export const TableColumnsSelector = ({
|
|
|
56
100
|
<DropdownMenu
|
|
57
101
|
menuListProps={{
|
|
58
102
|
sx: {
|
|
59
|
-
padding: '
|
|
103
|
+
padding: '0px',
|
|
60
104
|
width: '250px',
|
|
61
105
|
},
|
|
62
106
|
...props.menuListProps,
|
|
63
107
|
}}
|
|
64
108
|
anchor={({ open }: { open: (e: any) => void }) => (
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
borderRadius: '20px',
|
|
70
|
-
}}
|
|
71
|
-
variant="contained"
|
|
72
|
-
background={theme.palette.surface.grey}
|
|
73
|
-
hoverBackground={theme.palette.surface.grey}
|
|
74
|
-
color={theme.palette.text.primary}
|
|
75
|
-
endIcon={<KeyboardArrowDown />}
|
|
76
|
-
>
|
|
77
|
-
Columns
|
|
78
|
-
</Button>
|
|
109
|
+
<ColumnsAnchor
|
|
110
|
+
handleClick={open}
|
|
111
|
+
showDot={Object.values(columnVisibilityModel).includes(false)}
|
|
112
|
+
/>
|
|
79
113
|
)}
|
|
80
114
|
menuProps={{
|
|
81
115
|
...props.menuProps,
|
|
@@ -99,9 +133,9 @@ export const TableColumnsSelector = ({
|
|
|
99
133
|
/>
|
|
100
134
|
}
|
|
101
135
|
menuListContainerSx={{
|
|
102
|
-
margin: '
|
|
103
|
-
|
|
104
|
-
|
|
136
|
+
margin: '12px 12px 0px 12px',
|
|
137
|
+
height: '310px',
|
|
138
|
+
overflowY: 'scroll',
|
|
105
139
|
}}
|
|
106
140
|
menu={filteredOptions.map((item, index) => (
|
|
107
141
|
<SingleCheckBox
|
|
@@ -111,7 +145,11 @@ export const TableColumnsSelector = ({
|
|
|
111
145
|
sx: {
|
|
112
146
|
display: 'flex',
|
|
113
147
|
justifyContent: 'space-between',
|
|
114
|
-
|
|
148
|
+
margin: '0px',
|
|
149
|
+
width: '100%',
|
|
150
|
+
'.MuiFormControlLabel-label': {
|
|
151
|
+
width: '100%',
|
|
152
|
+
},
|
|
115
153
|
},
|
|
116
154
|
}}
|
|
117
155
|
icon={<Icons.VisibilityIcon />}
|
|
@@ -134,6 +172,70 @@ export const TableColumnsSelector = ({
|
|
|
134
172
|
}}
|
|
135
173
|
/>
|
|
136
174
|
))}
|
|
175
|
+
menuSlot={({ close }) => {
|
|
176
|
+
if (filteredOptions.length === 0)
|
|
177
|
+
return (
|
|
178
|
+
<EmptyIllustration
|
|
179
|
+
message="No Options Found"
|
|
180
|
+
imageSize="100px"
|
|
181
|
+
containerProps={{
|
|
182
|
+
height: '310px',
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
);
|
|
186
|
+
return filteredOptions.map((item, index) => (
|
|
187
|
+
<SingleCheckBox
|
|
188
|
+
key={index}
|
|
189
|
+
formControlLabelProps={{
|
|
190
|
+
labelPlacement: 'start',
|
|
191
|
+
sx: {
|
|
192
|
+
display: 'flex',
|
|
193
|
+
justifyContent: 'space-between',
|
|
194
|
+
margin: '0px',
|
|
195
|
+
width: '100%',
|
|
196
|
+
'.MuiFormControlLabel-label': {
|
|
197
|
+
width: '100%',
|
|
198
|
+
},
|
|
199
|
+
borderBottom: `1px solid ${theme.palette.secondary.main}`,
|
|
200
|
+
},
|
|
201
|
+
}}
|
|
202
|
+
icon={<Icons.VisibilityIcon />}
|
|
203
|
+
checkedIcon={<Icons.VisibilityOffIcon />}
|
|
204
|
+
checked={!columnVisibilityModel[item.field]}
|
|
205
|
+
label={
|
|
206
|
+
<Typography
|
|
207
|
+
color={
|
|
208
|
+
!columnVisibilityModel[item.field]
|
|
209
|
+
? theme.palette.text.tertiary
|
|
210
|
+
: theme.palette.text.primary
|
|
211
|
+
}
|
|
212
|
+
variant="subtitle3"
|
|
213
|
+
>
|
|
214
|
+
{item.headerName}
|
|
215
|
+
</Typography>
|
|
216
|
+
}
|
|
217
|
+
onChange={(e) => {
|
|
218
|
+
handleCheckboxChange(item, e.target.checked);
|
|
219
|
+
}}
|
|
220
|
+
/>
|
|
221
|
+
));
|
|
222
|
+
}}
|
|
223
|
+
useMenuSlot
|
|
224
|
+
menuFooter={
|
|
225
|
+
<TableColumnsSelectorMenuFooter
|
|
226
|
+
onClick={() => {
|
|
227
|
+
dispatch(
|
|
228
|
+
setColumnVisibilityModelForUniqueId({
|
|
229
|
+
uniqueId: uniqueId,
|
|
230
|
+
columnVisibilityModel: columns.reduce((acc, column) => {
|
|
231
|
+
acc[column.field] = true;
|
|
232
|
+
return acc;
|
|
233
|
+
}, {} as GridColumnVisibilityModel),
|
|
234
|
+
}),
|
|
235
|
+
);
|
|
236
|
+
}}
|
|
237
|
+
/>
|
|
238
|
+
}
|
|
137
239
|
/>
|
|
138
240
|
</>
|
|
139
241
|
);
|