@campxdev/shared 1.3.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,7 @@
1
- import {
2
- Checkbox,
3
- FormControl,
4
- FormControlLabel,
5
- FormGroup,
6
- Typography,
7
- } from '@mui/material'
1
+ import { Box, FormGroup, FormHelperText } from '@mui/material'
8
2
  import { Controller } from 'react-hook-form'
9
3
  import FormLabel from './FormLabel'
4
+ import SingleCheckbox from './SingleCheckbox'
10
5
 
11
6
  interface Props {
12
7
  label?: string
@@ -21,7 +16,6 @@ interface Props {
21
16
  export default function MultiCheckbox(props: Props) {
22
17
  const {
23
18
  name,
24
- size = 'small',
25
19
  control,
26
20
  label = '',
27
21
  options = [],
@@ -34,45 +28,34 @@ export default function MultiCheckbox(props: Props) {
34
28
  name={name}
35
29
  control={control}
36
30
  render={({ field, fieldState: { error } }) => (
37
- <>
38
- <FormLabel label={label} required={required} />
39
- <FormControl size={size} fullWidth>
40
- <FormGroup row={row} sx={{ flexWrap: 'wrap' }}>
41
- {options?.map((item, index) => (
42
- <FormControlLabel
43
- name={name}
44
- key={index}
45
- control={
46
- <Checkbox
47
- size="small"
48
- checked={field?.value
49
- ?.map((item: any) => item?.value)
50
- ?.includes(item?.value)}
51
- onChange={(e) => {
52
- let value = field.value || []
53
- if (e.target.checked) {
54
- let newValue = [...value, item]
55
- field.onChange(newValue)
56
- } else {
57
- let filteredValue = value.filter(
58
- (opt: any) => opt?.value !== item.value,
59
- )
60
- field.onChange(filteredValue)
61
- }
62
- }}
63
- />
31
+ <Box width="100%">
32
+ <FormLabel label={label} required={required} name={name} />
33
+ <FormGroup row={row} sx={{ flexWrap: 'wrap' }}>
34
+ {options?.map((item, index) => (
35
+ <SingleCheckbox
36
+ name={name}
37
+ key={index}
38
+ label={item.label}
39
+ checked={field?.value
40
+ ?.map((item: any) => item?.value)
41
+ ?.includes(item?.value)}
42
+ onChange={(e) => {
43
+ let value = field.value || []
44
+ if (e.target.checked) {
45
+ let newValue = [...value, item]
46
+ field.onChange(newValue)
47
+ } else {
48
+ let filteredValue = value.filter(
49
+ (opt: any) => opt?.value !== item.value,
50
+ )
51
+ field.onChange(filteredValue)
64
52
  }
65
- label={item.label}
66
- />
67
- ))}
68
- </FormGroup>
69
- </FormControl>
70
- {error && (
71
- <Typography variant="caption" color="error" sx={{ pl: '2px' }}>
72
- {error.message}
73
- </Typography>
74
- )}
75
- </>
53
+ }}
54
+ />
55
+ ))}
56
+ </FormGroup>
57
+ {error && <FormHelperText>{error.message}</FormHelperText>}
58
+ </Box>
76
59
  )}
77
60
  />
78
61
  )
@@ -40,7 +40,7 @@ export default function MultiSelect({
40
40
  <TextField
41
41
  {...params}
42
42
  variant="outlined"
43
- label={<FormLabel label={label} required={required} />}
43
+ label={<FormLabel label={label} required={required} name={name} />}
44
44
  />
45
45
  )}
46
46
  ChipProps={{
@@ -1,14 +1,52 @@
1
1
  import {
2
- Checkbox,
2
+ Box,
3
3
  FormControlLabel,
4
4
  Radio,
5
- Typography,
6
5
  RadioGroup as MuiRadioGroup,
7
- Box,
8
6
  RadioGroupProps,
9
- Stack,
7
+ styled,
10
8
  } from '@mui/material'
11
9
  import { ReactNode } from 'react'
10
+ import FormLabel from './FormLabel'
11
+
12
+ const BpIcon = styled('span')(({ theme }) => ({
13
+ borderRadius: '50%',
14
+ width: 18,
15
+ height: 18,
16
+ border: '1px solid #CBCBCB',
17
+ backgroundColor: '#f8f8f8',
18
+ '.Mui-focusVisible &': {
19
+ outline: '2px auto rgba(19,124,189,.6)',
20
+ outlineOffset: 2,
21
+ },
22
+ 'input:hover ~ &': {
23
+ backgroundColor: '#f8f8f8',
24
+ },
25
+ 'input:disabled ~ &': {
26
+ boxShadow: 'none',
27
+ background: 'rgba(206,217,224,.5)',
28
+ },
29
+ }))
30
+
31
+ const BpCheckedIcon = styled(BpIcon)(({ theme }) => ({
32
+ border: '1px solid #609D52',
33
+ background: '#f8f8f8',
34
+ backgroundImage:
35
+ 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))',
36
+ '&:before': {
37
+ backgroundColor: '#609D52',
38
+ content: '""',
39
+ display: 'block',
40
+ width: 8,
41
+ height: 8,
42
+ margin: '4px',
43
+ left: '2px',
44
+ borderRadius: '50%',
45
+ },
46
+ 'input:hover ~ &': {
47
+ backgroundColor: '#f8f8f8',
48
+ },
49
+ }))
12
50
 
13
51
  interface Props extends RadioGroupProps {
14
52
  label: string | ReactNode
@@ -29,29 +67,25 @@ export default function RadioGroup(props: Props) {
29
67
  required = false,
30
68
  value,
31
69
  onChange,
70
+ ...rest
32
71
  } = props
33
72
  return (
34
- <Box>
35
- <Box sx={{ display: 'flex' }}>
36
- {typeof label === 'string' ? (
37
- <>
38
- <Typography variant="subtitle2">{label}</Typography>
39
- {required && (
40
- <Typography fontSize={14} component={'span'} color="error">
41
- {' *'}
42
- </Typography>
43
- )}
44
- </>
45
- ) : (
46
- <>{label}</>
47
- )}
48
- </Box>
49
- <MuiRadioGroup value={value} onChange={onChange} row={row} name={name}>
73
+ <Box width="100%">
74
+ <FormLabel label={label} name={name} required={required} />
75
+ <MuiRadioGroup
76
+ value={value}
77
+ onChange={onChange}
78
+ row={row}
79
+ name={name}
80
+ {...rest}
81
+ >
50
82
  {options.map((item, index) => (
51
83
  <FormControlLabel
52
84
  key={index}
53
85
  value={item.value}
54
- control={<Radio />}
86
+ control={
87
+ <Radio checkedIcon={<BpCheckedIcon />} icon={<BpIcon />} />
88
+ }
55
89
  label={item.label}
56
90
  />
57
91
  ))}
@@ -1,9 +1,53 @@
1
- import { Checkbox, FormControlLabel, Typography } from '@mui/material'
2
- import { Controller } from 'react-hook-form'
1
+ import {
2
+ Checkbox,
3
+ CheckboxProps,
4
+ FormControlLabel,
5
+ styled,
6
+ } from '@mui/material'
7
+ import { ReactNode } from 'react'
3
8
 
4
- interface Props {
9
+ const BpIcon = styled('span')(({}) => ({
10
+ borderRadius: 3,
11
+ width: 18,
12
+ height: 18,
13
+ border: '1px solid #CBCBCB',
14
+ backgroundColor: '#F8F8F8',
15
+ '.Mui-focusVisible &': {
16
+ outline: '2px auto rgba(19,124,189,.6)',
17
+ outlineOffset: 2,
18
+ },
19
+ 'input:hover ~ &': {
20
+ backgroundColor: '#F8F8F8',
21
+ },
22
+ 'input:disabled ~ &': {
23
+ boxShadow: 'none',
24
+ background: 'rgba(206,217,224,.5)',
25
+ },
26
+ }))
27
+
28
+ const BpCheckedIcon = styled(BpIcon)(({ theme }) => ({
29
+ backgroundColor: '#F8F8F8',
30
+ border: `1px solid ${theme.palette.primary.main}`,
31
+ backgroundImage:
32
+ 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))',
33
+ '&:before': {
34
+ content: '""',
35
+ display: 'block',
36
+ width: 8,
37
+ height: 8,
38
+ margin: '4px',
39
+ left: '2px',
40
+ background: theme.palette.primary.main,
41
+ borderRadius: '2px',
42
+ },
43
+ 'input:hover ~ &': {
44
+ backgroundColor: '#F8F8F8',
45
+ },
46
+ }))
47
+
48
+ interface Props extends CheckboxProps {
5
49
  disabled?: boolean
6
- label: string
50
+ label: ReactNode
7
51
  name?: string
8
52
  size?: 'small' | 'medium'
9
53
  sx?: any
@@ -12,11 +56,19 @@ interface Props {
12
56
  }
13
57
 
14
58
  export default function SingleCheckbox(props: Props) {
15
- const { name, checked, size = 'medium', label = '', sx, onChange } = props
59
+ const { checked, size = 'medium', label = '', sx, onChange } = props
16
60
  return (
17
61
  <FormControlLabel
18
- sx={{ width: '100%', ...sx }}
19
- control={<Checkbox size={size} checked={checked} onChange={onChange} />}
62
+ control={
63
+ <Checkbox
64
+ size={size}
65
+ checked={checked}
66
+ onChange={onChange}
67
+ checkedIcon={<BpCheckedIcon />}
68
+ icon={<BpIcon />}
69
+ {...props}
70
+ />
71
+ }
20
72
  label={label}
21
73
  />
22
74
  )
@@ -1,126 +1,108 @@
1
+ import { ArrowDownward, KeyboardArrowDown } from '@mui/icons-material'
1
2
  import {
2
3
  FormControl,
3
- InputLabel,
4
4
  MenuItem,
5
- Select,
6
5
  SelectProps,
7
- Typography,
6
+ styled,
7
+ Select,
8
+ FormHelperText,
9
+ Box,
8
10
  } from '@mui/material'
9
11
  import { ReactNode } from 'react'
10
- import { Controller } from 'react-hook-form'
11
12
  import FormLabel from './FormLabel'
13
+
12
14
  type Props = {
13
- name?: string
14
- control?: any
15
15
  options: Array<{ label: ReactNode; value: any }>
16
- label?: string
17
- textColor?: string
18
16
  onChange?: (value: any) => void
19
17
  required?: boolean
20
- hookForm?: boolean
21
18
  firstItemEmpty?: boolean
19
+ helperText?: string
22
20
  } & SelectProps
23
21
 
24
- export default function SingleSelect(props: Props) {
25
- const {
26
- name = 'select',
27
- options = [],
28
- control,
29
- label,
30
- textColor,
31
- onChange,
32
- required,
33
- hookForm = true,
34
- firstItemEmpty = false,
35
- } = props
22
+ const StyledFormControl = styled(FormControl)(({ theme }) => ({
23
+ '& .MuiInputBase-root': {
24
+ '& legend': { display: 'none' },
25
+ '& .MuiSelect-select': {
26
+ boxSizing: 'border-box',
27
+ height: '50px',
28
+ padding: '14px',
29
+ },
30
+ '& .MuiSvgIcon-root': {
31
+ right: '14px',
32
+ },
33
+ },
34
+ }))
36
35
 
36
+ const PaperProps = {
37
+ elevation: 0,
38
+ sx: {
39
+ borderRadius: '10px',
40
+ borderTopRightRadius: 0,
41
+ borderTopLeftRadius: 0,
42
+ border: '1px solid #1212121A',
43
+ borderTop: 'none',
44
+ boxShadow: '0px 4px 16px #0000000F',
45
+ maxHeight: 360,
46
+ marginTop: '1px',
47
+ '& .MuiList-root': {
48
+ minWidth: '240px',
49
+ padding: 0,
50
+ '& li': {
51
+ height: '60px',
52
+ borderBottom: (theme) => theme.borders.grayLight,
53
+ ':hover': {
54
+ backgroundColor: 'rgba(0, 0, 0, 0.025)',
55
+ },
56
+ },
57
+ '& > :last-child': {
58
+ borderBottom: 'none',
59
+ },
60
+ },
61
+ },
62
+ }
63
+
64
+ export default function SingleSelect({
65
+ name = 'select',
66
+ options = [],
67
+ label,
68
+ onChange,
69
+ required,
70
+ value,
71
+ helperText,
72
+ firstItemEmpty = false,
73
+ ...props
74
+ }: Props) {
37
75
  const inputOptions = firstItemEmpty
38
76
  ? [{ label: 'All', value: '__empty__' }, ...options]
39
77
  : options
40
78
 
41
- if (!hookForm) {
42
- return (
43
- <>
44
- <FormControl fullWidth sx={props.sx}>
45
- <InputLabel id={name}>
46
- <FormLabel required={required} label={label} />
47
- </InputLabel>
48
- <Select
49
- multiple={false}
50
- variant="outlined"
51
- id={name}
52
- value={props.value}
53
- displayEmpty={firstItemEmpty}
54
- fullWidth
55
- label={label}
56
- MenuProps={{
57
- PaperProps: {
58
- sx: { maxHeight: 300 },
59
- },
60
- }}
61
- onChange={props.onChange}
62
- >
63
- {inputOptions?.map((item, index) => (
64
- <MenuItem key={index} value={item.value}>
65
- {item.label}
66
- </MenuItem>
67
- ))}
68
- </Select>
69
- </FormControl>
70
- </>
71
- )
72
- }
73
-
74
79
  return (
75
- <Controller
76
- name={name}
77
- control={control}
78
- render={({ field, fieldState: { error } }) => (
79
- <>
80
- <FormControl fullWidth>
81
- <InputLabel id={name}>
82
- <FormLabel required={required} label={label} />
83
- </InputLabel>
84
- <Select
85
- multiple={false}
86
- error={Boolean(error)}
87
- variant="outlined"
88
- sx={{ color: textColor }}
89
- fullWidth
90
- label={label}
91
- displayEmpty={firstItemEmpty}
92
- MenuProps={{
93
- PaperProps: {
94
- sx: { maxHeight: 300 },
95
- },
96
- }}
97
- value={field.value}
98
- onChange={(e) => {
99
- if (onChange) onChange(e.target.value)
100
- field.onChange(e.target.value)
101
- }}
102
- >
103
- {inputOptions?.map((item, index) => (
104
- <MenuItem key={index} value={item.value}>
105
- {item.label}
106
- </MenuItem>
107
- ))}
108
- </Select>
109
- </FormControl>
110
- {error && (
111
- <Typography
112
- fontSize={12}
113
- sx={{
114
- paddingLeft: '2px',
115
- marginTop: '2px',
116
- }}
117
- color="error"
118
- >
119
- {error.message}
120
- </Typography>
121
- )}
122
- </>
123
- )}
124
- />
80
+ <Box width="100%">
81
+ <FormLabel required={required} label={label} name={name} />
82
+ <StyledFormControl fullWidth>
83
+ <Select
84
+ id={name}
85
+ multiple={false}
86
+ variant="outlined"
87
+ value={value}
88
+ displayEmpty={firstItemEmpty}
89
+ fullWidth
90
+ label={label}
91
+ MenuProps={{
92
+ PaperProps: PaperProps,
93
+ }}
94
+ IconComponent={KeyboardArrowDown}
95
+ onChange={onChange}
96
+ {...props}
97
+ >
98
+ {inputOptions?.map((item, index) => (
99
+ <MenuItem key={index} value={item.value}>
100
+ {item.label}
101
+ </MenuItem>
102
+ ))}
103
+ </Select>
104
+ {helperText && <FormHelperText>{helperText}</FormHelperText>}
105
+ </StyledFormControl>
106
+ </Box>
125
107
  )
126
108
  }
@@ -1,50 +1,46 @@
1
1
  import {
2
+ Box,
3
+ styled,
2
4
  TextField as MuiTextField,
3
5
  TextFieldProps as MuiTextFieldProps,
4
- Typography,
5
6
  } from '@mui/material'
6
- import React from 'react'
7
- import { Controller } from 'react-hook-form'
8
- import FormLabel from './FormLabel'
7
+ import FieldLabel from './FormLabel'
9
8
 
10
9
  type MyTextFieldProps = MuiTextFieldProps & {
11
- control?: any
12
- label?: string
13
10
  name?: string
14
11
  value?: any
15
- hookForm?: boolean
16
12
  required?: boolean
17
- handleChange?: React.ChangeEventHandler<
18
- HTMLTextAreaElement | HTMLInputElement
19
- >
20
13
  }
21
14
 
15
+ const StyledTextField = styled(MuiTextField)(({ theme }) => ({
16
+ '& label': {
17
+ display: 'none',
18
+ },
19
+ '& legend': {
20
+ '& span': {
21
+ display: 'none',
22
+ },
23
+ },
24
+ }))
25
+
22
26
  export default function TextField({
23
27
  name,
24
- control,
25
28
  label,
26
29
  value,
27
- handleChange,
30
+ onChange,
28
31
  required = false,
29
- hookForm = true,
30
32
  ...rest
31
33
  }: MyTextFieldProps) {
32
34
  return (
33
- <MuiTextField
34
- label={
35
- <>
36
- {label}
37
- {required && (
38
- <Typography fontSize={14} component={'span'} color="error">
39
- {' *'}
40
- </Typography>
41
- )}
42
- </>
43
- }
44
- value={value}
45
- name={name}
46
- onChange={handleChange}
47
- {...rest}
48
- />
35
+ <Box width="100%">
36
+ <FieldLabel label={label} required={required} name={name} />
37
+ <StyledTextField
38
+ id={name}
39
+ value={value}
40
+ name={name}
41
+ onChange={onChange}
42
+ {...rest}
43
+ />
44
+ </Box>
49
45
  )
50
46
  }
@@ -1,34 +1,12 @@
1
1
  import { Visibility, VisibilityOff } from '@mui/icons-material'
2
- import {
3
- Alert,
4
- Box,
5
- Button,
6
- IconButton,
7
- InputAdornment,
8
- Stack,
9
- styled,
10
- } from '@mui/material'
2
+ import { Alert, Box, IconButton, InputAdornment, Stack } from '@mui/material'
11
3
  import axiosBase from 'axios'
12
4
  import Cookies from 'js-cookie'
13
5
  import { useState } from 'react'
14
6
  import { useForm } from 'react-hook-form'
7
+ import ActionButton from './ActionButton'
15
8
  import { FormTextField } from './HookForm'
16
9
 
17
- export const StyledTextField = styled(FormTextField)(({ theme }) => ({
18
- '& .MuiInputBase-root': {
19
- minHeight: '60px',
20
- },
21
- '& .MuiOutlinedInput-input': {
22
- padding: '18.5px 14px',
23
- },
24
- }))
25
-
26
- export const StyledButton = styled(Button)(({ theme }) => ({
27
- borderRadius: '10px',
28
- height: '60px',
29
- fontSize: '18px',
30
- }))
31
-
32
10
  export function LoginForm({ loginUrl }: { loginUrl?: string }) {
33
11
  const [showPassword, setShowPassword] = useState(false)
34
12
  const { handleSubmit, control } = useForm()
@@ -55,10 +33,9 @@ export function LoginForm({ loginUrl }: { loginUrl?: string }) {
55
33
  return (
56
34
  <Box sx={{ maxWidth: '500px' }} margin="0 auto" padding={'0 1rem'}>
57
35
  <form onSubmit={handleSubmit(onSubmit)}>
58
- <Stack gap={'40px'}>
36
+ <Stack gap={'30px'}>
59
37
  <Box>
60
- <StyledTextField
61
- size="medium"
38
+ <FormTextField
62
39
  control={control}
63
40
  name="username"
64
41
  label="User ID"
@@ -66,7 +43,7 @@ export function LoginForm({ loginUrl }: { loginUrl?: string }) {
66
43
  />
67
44
  </Box>
68
45
  <Box>
69
- <StyledTextField
46
+ <FormTextField
70
47
  control={control}
71
48
  name="password"
72
49
  label="Password"
@@ -88,7 +65,7 @@ export function LoginForm({ loginUrl }: { loginUrl?: string }) {
88
65
  }}
89
66
  />
90
67
  </Box>
91
- <StyledButton type="submit">Login</StyledButton>
68
+ <ActionButton type="submit">Login</ActionButton>
92
69
  </Stack>
93
70
  </form>
94
71
  {error && (
@@ -23,6 +23,9 @@ const StyledBox = styled(Box, {
23
23
  gap: '1rem',
24
24
  alignItems: 'center',
25
25
  marginLeft: 'auto',
26
+ '& .MuiButton-root': {
27
+ height: '40px',
28
+ },
26
29
  },
27
30
  }))
28
31
 
@@ -13,7 +13,6 @@ import {
13
13
  } from '@mui/material'
14
14
  import { useEffect, useMemo, useState } from 'react'
15
15
  import { usePagination, useRowSelect, useTable } from 'react-table'
16
- import ErrorBoundary from '../ErrorBoundary'
17
16
  import BatchActionsHeader from './BatchActionsHeader'
18
17
  import { SortAscIcon, SortDescIcon, SortIcon } from './Icons'
19
18
  import { RenderTableBody } from './RenderTableBody'
@@ -74,6 +73,7 @@ export default function TableComponent({
74
73
  select = {
75
74
  enable: false,
76
75
  },
76
+ onRowClick,
77
77
  }: TableProps) {
78
78
  const [sort, setSort] = useState<Sort>({})
79
79
 
@@ -97,7 +97,6 @@ export default function TableComponent({
97
97
  pageCount,
98
98
  gotoPage,
99
99
  setPageSize,
100
- selectedFlatRows,
101
100
  toggleAllRowsSelected,
102
101
  state: { pageIndex, pageSize, selectedRowIds },
103
102
  } = useTable(
@@ -217,6 +216,7 @@ export default function TableComponent({
217
216
  ))}
218
217
  </TableHead>
219
218
  <RenderTableBody
219
+ onRowClick={onRowClick}
220
220
  colLength={columns?.length}
221
221
  loading={loading || refetching}
222
222
  getTableBodyProps={getTableBodyProps}