@campxdev/react-blueprint 1.7.10 → 1.7.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campxdev/react-blueprint",
3
- "version": "1.7.10",
3
+ "version": "1.7.11",
4
4
  "main": "./export.ts",
5
5
  "dependencies": {
6
6
  "@emotion/react": "^11.13.3",
package/src/App.tsx CHANGED
@@ -1,7 +1,8 @@
1
- import { LocalizationProvider } from '@mui/x-date-pickers';
2
- import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3';
1
+ import { Button } from '@mui/material';
2
+ import { useForm } from 'react-hook-form';
3
+
3
4
  import './App.css';
4
- import { ActivityLogView } from './components/export';
5
+ import { FileUpload, FormControlWrapper } from './components/export';
5
6
 
6
7
  interface RowType {
7
8
  lastName: string;
@@ -10,82 +11,25 @@ interface RowType {
10
11
  }
11
12
 
12
13
  function App() {
14
+ const { control, watch, handleSubmit } = useForm({});
15
+
16
+ const onSubmit = (formData: any) => {
17
+ console.log(formData);
18
+ };
19
+
13
20
  return (
14
21
  <div
15
22
  style={{
16
23
  display: 'flex',
17
24
  justifyContent: 'flex-start',
18
25
  paddingLeft: '16px',
26
+ flexDirection: 'column',
19
27
  }}
20
28
  >
21
- <LocalizationProvider dateAdapter={AdapterDateFns}>
22
- <ActivityLogView
23
- activitiesData={[
24
- {
25
- userName: 'ss',
26
- action: 'create',
27
- message: 's',
28
- timestamp: new Date().toISOString(),
29
- },
30
- {
31
- userName: 'ss',
32
- action: 'update',
33
- message: 's',
34
- timestamp: new Date().toISOString(),
35
- },
36
- {
37
- userName: 'ss',
38
- action: 'update',
39
- message: 's',
40
- timestamp: new Date().toISOString(),
41
- },
42
- {
43
- userName: 'ss',
44
- action: 'update',
45
- message: 's',
46
- timestamp: new Date().toISOString(),
47
- },
48
- {
49
- userName: 'ss',
50
- action: 'update',
51
- message: 's',
52
- timestamp: new Date().toISOString(),
53
- },
54
- {
55
- userName: 'ss',
56
- action: 'delete',
57
- message: 's',
58
- timestamp: new Date().toISOString(),
59
- },
60
- {
61
- userName: 'ss',
62
- action: 'update',
63
- message: 's',
64
- timestamp: new Date().toISOString(),
65
- },
66
- {
67
- userName: 'ss',
68
- action: 'update',
69
- message: 's',
70
- timestamp: new Date().toISOString(),
71
- },
72
- ]}
73
- isFetchingNextPage={false}
74
- fetchNextPage={function (): void {
75
- // throw new Error('Function not implemented.');
76
- }}
77
- hasNextPage={undefined}
78
- fromDate={null}
79
- toDate={null}
80
- setFromDate={function (date: Date | null): void {
81
- // throw new Error('Function not implemented.');
82
- }}
83
- setToDate={function (date: Date | null): void {
84
- // throw new Error('Function not implemented.');
85
- }}
86
- isLoading={false}
87
- />
88
- </LocalizationProvider>
29
+ <FormControlWrapper control={control}>
30
+ <FileUpload label={'Files'} name="daaku" files={watch().daaku} />
31
+ </FormControlWrapper>
32
+ <Button onClick={handleSubmit(onSubmit)}>Submit</Button>
89
33
  </div>
90
34
  );
91
35
  }
@@ -0,0 +1,45 @@
1
+ import { useTheme } from '@mui/material';
2
+
3
+ export const ThreeDotsMenuIcon = ({
4
+ size = 16,
5
+ color,
6
+ backgroundColor,
7
+ }: {
8
+ size?: number;
9
+ color?: string;
10
+ backgroundColor?: string;
11
+ }) => {
12
+ const theme = useTheme();
13
+ const fill = color ?? theme.palette.primary.main;
14
+ const background = backgroundColor || theme.palette.secondary.main;
15
+ return (
16
+ <svg
17
+ width={size}
18
+ height={size}
19
+ viewBox="0 0 24 24"
20
+ fill="none"
21
+ xmlns="http://www.w3.org/2000/svg"
22
+ >
23
+ <g clip-path="url(#clip0_462_9729)">
24
+ <rect width="24" height="24" rx="4" fill={background} />
25
+ <path
26
+ d="M16 11.9999C16 12.8836 16.7163 13.5999 17.6 13.5999C18.4836 13.5999 19.2 12.8836 19.2 11.9999C19.2 11.1162 18.4836 10.3999 17.6 10.3999C16.7163 10.3999 16 11.1162 16 11.9999Z"
27
+ fill={fill}
28
+ />
29
+ <path
30
+ d="M10.4 11.9999C10.4 12.8836 11.1163 13.5999 12 13.5999C12.8836 13.5999 13.6 12.8836 13.6 11.9999C13.6 11.1162 12.8836 10.3999 12 10.3999C11.1163 10.3999 10.4 11.1162 10.4 11.9999Z"
31
+ fill={fill}
32
+ />
33
+ <path
34
+ d="M4.8 11.9999C4.8 12.8836 5.51634 13.5999 6.4 13.5999C7.28366 13.5999 8 12.8836 8 11.9999C8 11.1162 7.28366 10.3999 6.4 10.3999C5.51634 10.3999 4.8 11.1162 4.8 11.9999Z"
35
+ fill={fill}
36
+ />
37
+ </g>
38
+ <defs>
39
+ <clipPath id="clip0_462_9729">
40
+ <rect width="24" height="24" rx="4" fill="white" />
41
+ </clipPath>
42
+ </defs>
43
+ </svg>
44
+ );
45
+ };
@@ -110,6 +110,7 @@ import { StudentsIcon } from './IconComponents/StudentsIcon';
110
110
  import { SuccessFilledIcon } from './IconComponents/SuccessFilledIcon';
111
111
  import { TasksIcon } from './IconComponents/TasksIcon';
112
112
  import { TextLocalIcon } from './IconComponents/TextLocalIcon';
113
+ import { ThreeDotsMenuIcon } from './IconComponents/ThreeDotsMenuIcon';
113
114
  import { TicketSystemIcon } from './IconComponents/TicketingSystemIcon';
114
115
  import { TicketsIcon } from './IconComponents/TicketsIcon';
115
116
  import { TimeTableIcon } from './IconComponents/TimeTableIcon';
@@ -133,6 +134,7 @@ export const Icons = {
133
134
  RedoIcon,
134
135
  WhatsappIcon,
135
136
  AssignmentIcon,
137
+ ThreeDotsMenuIcon,
136
138
  ReportIssueIcon,
137
139
  SmsIcon,
138
140
  EmailIcon,
@@ -24,7 +24,7 @@ export const StyledButton = styled(Button)(({ theme }) => ({
24
24
 
25
25
  export const StyledImage = styled('img')(({ theme }) => ({
26
26
  height: '216px',
27
- width: '385px',
27
+ width: '400px',
28
28
  objectFit: 'cover',
29
29
  }));
30
30
 
@@ -0,0 +1,95 @@
1
+ import { StackProps } from '@mui/material';
2
+ import {
3
+ DateTimePicker as MuiDateTimePicker,
4
+ DateTimePickerProps as MuiDateTimePickerProps,
5
+ PickersShortcutsItem,
6
+ PickerValidDate,
7
+ } from '@mui/x-date-pickers';
8
+ import { format as DateFnsFormat } from 'date-fns';
9
+
10
+ import { Icons } from '../../export';
11
+ import { LabelWrapper } from '../LabelWrapper/LabelWrapper';
12
+
13
+ type DateTimePickerProps<
14
+ TDate extends PickerValidDate,
15
+ TEnableAccessibleFieldDOMStructure extends boolean = false,
16
+ > = {
17
+ format?:
18
+ | 'yyyy'
19
+ | 'MMMM yyyy'
20
+ | 'MMM yyyy'
21
+ | 'dd MMMM yyyy'
22
+ | 'dd/MM/yyyy'
23
+ | 'MM/dd/yyyy'
24
+ | 'yyyy-MM-dd'
25
+ | 'yyyy-MM-dd hh:mm a'
26
+ | 'yyyy-MM-dd HH:mm'
27
+ | 'dd MMM yyyy HH:mm'
28
+ | 'dd MMM yyyy hh:mm a'
29
+ | 'dd/MM/yyyy hh:mm a'
30
+ | 'dd/MM/yyyy HH:mm'
31
+ | 'hh:mm a'
32
+ | 'HH:mm'
33
+ | 'hh:mm:ss a'
34
+ | 'HH:mm:ss'
35
+ | 'MMM dd, yyyy hh:mm a'
36
+ | 'MMMM dd, yyyy HH:mm'
37
+ | 'EEE, MMM dd yyyy'
38
+ | 'EEEE, MMMM dd, yyyy';
39
+ views?: ('year' | 'month' | 'day' | 'hours' | 'minutes' | 'seconds')[];
40
+ helperText?: string;
41
+ placeholder?: string;
42
+ shortcutsItems?: PickersShortcutsItem<any>[];
43
+ required?: boolean;
44
+ containerProps?: StackProps;
45
+ openPickerIcon?: React.ElementType;
46
+ } & MuiDateTimePickerProps<TDate, TEnableAccessibleFieldDOMStructure>;
47
+
48
+ export const DateTimePicker = <
49
+ TDate extends PickerValidDate,
50
+ TEnableAccessibleFieldDOMStructure extends boolean = false,
51
+ >({
52
+ label,
53
+ name,
54
+ required = false,
55
+ format = 'dd MMM yyyy hh:mm a',
56
+ views = ['year', 'month', 'day', 'hours', 'minutes', 'seconds'],
57
+ helperText,
58
+ placeholder = '',
59
+ shortcutsItems = [],
60
+ openPickerIcon: Icon = Icons.NoteIcon,
61
+ containerProps,
62
+ value,
63
+ ...rest
64
+ }: DateTimePickerProps<TDate, TEnableAccessibleFieldDOMStructure>) => {
65
+ return (
66
+ <LabelWrapper
67
+ label={label}
68
+ required={required}
69
+ name={name}
70
+ containerProps={containerProps}
71
+ >
72
+ <MuiDateTimePicker
73
+ format={format}
74
+ views={views}
75
+ defaultValue={value}
76
+ slotProps={{
77
+ textField: {
78
+ helperText,
79
+ placeholder,
80
+ },
81
+ shortcuts: {
82
+ items: shortcutsItems,
83
+ },
84
+ }}
85
+ slots={{
86
+ openPickerIcon: Icon,
87
+ }}
88
+ dayOfWeekFormatter={(day: any) => {
89
+ return `${DateFnsFormat(day, 'EEEE').slice(0, 2)}.`;
90
+ }}
91
+ {...rest}
92
+ />
93
+ </LabelWrapper>
94
+ );
95
+ };
@@ -0,0 +1,215 @@
1
+ import {
2
+ Box,
3
+ FormLabel,
4
+ Stack,
5
+ styled,
6
+ SxProps,
7
+ useTheme,
8
+ } from '@mui/material';
9
+ import { IconButtons, Icons, PreviewFiles, Typography } from '../../export';
10
+
11
+ export type FileUploadProps = {
12
+ label: string;
13
+ name: string;
14
+ disabled?: boolean;
15
+ files?: File[];
16
+ onChange?: (files: File[]) => void;
17
+ handleRemove?: (index: number) => void;
18
+ accept?: 'image/*' | '.pdf' | '.docx' | '.txt' | '*';
19
+ onInvalidFile?: (file: File) => void;
20
+ inputText?: string;
21
+ multiple?: boolean;
22
+ hideDeleteButton?: boolean;
23
+ errorText?: string;
24
+ sx?: SxProps;
25
+ showImage?: boolean;
26
+ previewSx?: SxProps;
27
+ };
28
+
29
+ export const FileUpload = ({
30
+ label,
31
+ name = 'file-input',
32
+ disabled = false,
33
+ onChange,
34
+ handleRemove,
35
+ files = [],
36
+ accept = '*',
37
+ inputText,
38
+ onInvalidFile,
39
+ hideDeleteButton = false,
40
+ multiple = true,
41
+ errorText,
42
+ showImage,
43
+ previewSx,
44
+ sx,
45
+ }: FileUploadProps) => {
46
+ const theme = useTheme();
47
+
48
+ if (!onChange) {
49
+ return <Typography>onChange Missing</Typography>;
50
+ }
51
+
52
+ const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
53
+ if (event.target.files) {
54
+ const newFiles = Array.from(event.target.files);
55
+ const validFiles: File[] = [];
56
+ const invalidFiles: File[] = [];
57
+
58
+ newFiles.forEach((file) => {
59
+ if (
60
+ accept === '*' ||
61
+ file.type.match(accept) ||
62
+ file.name.match(accept)
63
+ ) {
64
+ validFiles.push(file);
65
+ } else {
66
+ invalidFiles.push(file);
67
+ }
68
+ });
69
+
70
+ invalidFiles.forEach((file) => onInvalidFile?.(file));
71
+
72
+ if (validFiles.length > 0) {
73
+ if (multiple) {
74
+ onChange([...files, ...validFiles]);
75
+ } else {
76
+ onChange([validFiles[0]]);
77
+ }
78
+ }
79
+ }
80
+ };
81
+
82
+ return (
83
+ <Stack sx={sx}>
84
+ <Typography variant="label1">{label}</Typography>
85
+ <input
86
+ accept={accept}
87
+ style={{ display: 'none' }}
88
+ id={name}
89
+ name={name}
90
+ type="file"
91
+ multiple={multiple}
92
+ disabled={disabled}
93
+ onChange={handleFileChange}
94
+ />
95
+
96
+ <FormLabel htmlFor={name}>
97
+ <StyledFileSelectorContainer>
98
+ <Stack display={'flex'} alignItems={'center'}>
99
+ <Icons.ExportIcon size={20} />
100
+ <Typography
101
+ color={
102
+ disabled
103
+ ? theme.palette.secondary.dark
104
+ : theme.palette.primary.main
105
+ }
106
+ variant="label2"
107
+ >
108
+ {inputText ?? 'Upload Files'}
109
+ </Typography>
110
+ </Stack>
111
+ </StyledFileSelectorContainer>
112
+ {errorText && (
113
+ <Typography
114
+ sx={{
115
+ display: 'flex',
116
+ alignItems: 'flex-end',
117
+ justifyContent: 'flex-end',
118
+ color: theme.palette.highlight.highlightRed,
119
+ }}
120
+ variant="caption"
121
+ >
122
+ {errorText}
123
+ </Typography>
124
+ )}
125
+ </FormLabel>
126
+
127
+ <Box display="flex" gap="12px" flexWrap="wrap">
128
+ {showImage ? (
129
+ files.map((file, index) => (
130
+ <StyledSelectedFileContainer key={index}>
131
+ <Box
132
+ sx={{
133
+ height: '120px',
134
+ display: 'flex',
135
+ overflow: 'hidden',
136
+ borderRadius: '8px',
137
+ }}
138
+ >
139
+ <img
140
+ src={URL.createObjectURL(file)}
141
+ style={{
142
+ height: '100%',
143
+ width: '100%',
144
+ objectFit: 'cover',
145
+ }}
146
+ alt={`Preview ${index}`}
147
+ />
148
+ </Box>
149
+
150
+ {!disabled && !hideDeleteButton && (
151
+ <IconButtons.DeleteButton
152
+ onClick={() => {
153
+ const updatedFiles = [...files];
154
+ updatedFiles.splice(index, 1);
155
+ onChange(updatedFiles);
156
+ }}
157
+ size="small"
158
+ />
159
+ )}
160
+ </StyledSelectedFileContainer>
161
+ ))
162
+ ) : (
163
+ <Box
164
+ sx={{
165
+ display: 'flex',
166
+ justifyContent: 'center',
167
+ alignItems: 'center',
168
+ padding: '8px',
169
+ overflow: 'hidden',
170
+ backgroundColor: theme.palette.background.default,
171
+ borderRadius: '8px',
172
+ }}
173
+ >
174
+ <PreviewFiles
175
+ sx={previewSx}
176
+ files={files}
177
+ onChange={(newFiles) => onChange?.(newFiles)}
178
+ />
179
+ </Box>
180
+ )}
181
+ </Box>
182
+ </Stack>
183
+ );
184
+ };
185
+
186
+ const StyledSelectedFileContainer = styled(Box)(({ theme }) => ({
187
+ borderRadius: '10px',
188
+ position: 'relative',
189
+ flex: '1 1 auto',
190
+ textAlign: 'center',
191
+ marginTop: '5px',
192
+ minWidth: '400px',
193
+ '& > button': {
194
+ position: 'absolute',
195
+ right: '-4%',
196
+ top: '-10%',
197
+ },
198
+ }));
199
+
200
+ const StyledFileSelectorContainer = styled(Box)(({ theme }) => ({
201
+ border: '1.5px dotted',
202
+ height: '120px',
203
+ display: 'flex',
204
+ width: '100%',
205
+ borderRadius: '5px',
206
+ borderColor: theme.palette.primary.main,
207
+ justifyContent: 'center',
208
+ alignItems: 'center',
209
+ '&:hover': {
210
+ borderColor: theme.palette.primary.light,
211
+ backgroundColor: theme.palette.secondary.light,
212
+ transition:
213
+ 'border-color 0.2s ease-in-out, background-color 0.2s ease-in-out',
214
+ },
215
+ }));
@@ -2,6 +2,7 @@ import { Stack, SxProps } from '@mui/material';
2
2
  import { TextFieldProps } from '@mui/material/TextField';
3
3
  import React, { ReactElement, ReactNode, isValidElement } from 'react';
4
4
  import { Control, Controller, FieldValues, Path } from 'react-hook-form';
5
+ import { FileUpload, FileUploadProps } from '../export';
5
6
  import FormActions, { FormActionsProps } from '../FormActions/FormActions';
6
7
 
7
8
  interface FormControlWrapperProps<T extends FieldValues = FieldValues> {
@@ -21,6 +22,8 @@ type ControlledElementProps<T extends FieldValues = FieldValues> = {
21
22
  error?: boolean;
22
23
  helperText?: ReactNode;
23
24
  children?: ReactNode;
25
+ files?: File[];
26
+ onChange?: (files: File[]) => void;
24
27
  [key: string]: any;
25
28
  } & TextFieldProps;
26
29
 
@@ -47,10 +50,19 @@ export function FormControlWrapper<T extends FieldValues = FieldValues>({
47
50
  name={name}
48
51
  control={control}
49
52
  render={({ field, fieldState: { error } }) => {
53
+ if (element.type === FileUpload) {
54
+ return React.cloneElement(element, {
55
+ ...(restProps as Partial<FileUploadProps>),
56
+ files: field.value || [],
57
+ ...field,
58
+ errorText: error ? error.message : undefined,
59
+ } as FileUploadProps);
60
+ }
50
61
  const additionalProps =
51
62
  element.type === 'input' && restProps.type === 'checkbox'
52
63
  ? { checked: field.value }
53
64
  : { value: field.value };
65
+ console.log(error);
54
66
  return React.cloneElement(element, {
55
67
  ...restProps,
56
68
  ...field,
@@ -1,5 +1,7 @@
1
1
  export * from './Button/Button';
2
2
  export * from './DatePicker/DatePicker';
3
+ export * from './DateTimePicker/DateTimePicker';
4
+ export * from './FileUpload/FileUpload';
3
5
  export * from './FormActions/FormActions';
4
6
  export * from './FormControlWrapper/FormControlWrapper';
5
7
  export * from './FormWrapper/FormWrapper';
@@ -1,4 +1,10 @@
1
- import { IconButton, Stack, useMediaQuery, useTheme } from '@mui/material';
1
+ import {
2
+ IconButton,
3
+ Stack,
4
+ SxProps,
5
+ useMediaQuery,
6
+ useTheme,
7
+ } from '@mui/material';
2
8
  import { ReactNode } from 'react';
3
9
  import { ReportIssueIcon } from '../../Assets/Icons/IconComponents/ReportIssueIcon';
4
10
  import { Typography } from '../../DataDisplay/Typography/Typography';
@@ -18,6 +24,7 @@ export interface AppHeaderProps {
18
24
  profileSx?: any;
19
25
  onLogoutClick?: any;
20
26
  showActiveDevices?: boolean;
27
+ headerSx?: SxProps;
21
28
  }
22
29
 
23
30
  export const AppHeader = ({
@@ -31,6 +38,7 @@ export const AppHeader = ({
31
38
  collapsed,
32
39
  institutionsData,
33
40
  showActiveDevices = true,
41
+ headerSx,
34
42
  }: AppHeaderProps) => {
35
43
  const theme = useTheme();
36
44
  const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
@@ -39,7 +47,11 @@ export const AppHeader = ({
39
47
  window.open('https://helpdesk.campx.in/helpdesk/my-tickets', '_blank');
40
48
  };
41
49
  return (
42
- <StyledHeader collapsed={collapsed} className="appHeader">
50
+ <StyledHeader
51
+ collapsed={collapsed}
52
+ className="appHeader"
53
+ headerSx={headerSx}
54
+ >
43
55
  <Typography variant={isSmallScreen ? 'subtitle3' : 'subtitle2'}>
44
56
  {clientName}
45
57
  </Typography>
@@ -2,7 +2,14 @@ import { Box, Divider, styled } from '@mui/material';
2
2
  import { Link } from 'react-router-dom';
3
3
 
4
4
  export const StyledHeader = styled('header')(
5
- ({ theme }: { theme?: any; collapsed: boolean }) => ({
5
+ ({
6
+ theme,
7
+ headerSx,
8
+ }: {
9
+ theme?: any;
10
+ collapsed: boolean;
11
+ headerSx?: any;
12
+ }) => ({
6
13
  display: 'flex',
7
14
  flexDirection: 'row',
8
15
  alignItems: 'center',
@@ -17,10 +24,11 @@ export const StyledHeader = styled('header')(
17
24
  [theme.breakpoints.down('md')]: {
18
25
  height: '50px',
19
26
  minHeight: '50px',
20
- width: 'calc(100% - 84px)',
27
+ width: headerSx?.width?.sm ? headerSx?.width?.sm : 'calc(100% - 84px)',
21
28
  marginTop: '12px',
22
29
  padding: '0 12px',
23
30
  },
31
+ ...headerSx,
24
32
  }),
25
33
  );
26
34
 
@@ -1,5 +1,9 @@
1
1
  import { Box, BoxProps, styled } from '@mui/material';
2
2
 
3
+ export type PageContentProps = {
4
+ variant?: 'stepper' | 'standard';
5
+ } & BoxProps;
6
+
3
7
  const PageContentContainer = styled(Box)(({ theme }) => ({
4
8
  display: 'flex',
5
9
  flexDirection: 'column',
@@ -11,8 +15,21 @@ const PageContentContainer = styled(Box)(({ theme }) => ({
11
15
  borderRadius: '8px',
12
16
  }));
13
17
 
14
- export const PageContent = (props: BoxProps) => {
15
- return (
18
+ const PageStepperContainer = styled(Box)(({ theme }) => ({
19
+ display: 'flex',
20
+ alignItems: 'center',
21
+ flexDirection: 'column',
22
+ justifyContent: 'flex-start',
23
+ gap: '10px',
24
+ }));
25
+
26
+ export const PageContent = ({
27
+ variant = 'standard',
28
+ ...props
29
+ }: PageContentProps) => {
30
+ return variant == 'stepper' ? (
31
+ <PageStepperContainer {...props}>{props.children}</PageStepperContainer>
32
+ ) : (
16
33
  <PageContentContainer gap="12px" {...props}>
17
34
  {props.children}
18
35
  </PageContentContainer>
@@ -0,0 +1,39 @@
1
+ import { Box, BoxProps, styled } from '@mui/material';
2
+ import { ReactNode } from 'react';
3
+ import { Typography } from '../../export';
4
+
5
+ export type StepperTitleProps = {
6
+ title?: string;
7
+ isShowTitle?: boolean;
8
+ content: ReactNode;
9
+ contentProps?: BoxProps;
10
+ titleProps?: BoxProps;
11
+ };
12
+
13
+ const StepperTitleContainer = styled(Box)(({ theme }) => ({
14
+ borderRadius: '8px',
15
+ minHeight: '100px',
16
+ minWidth: '60%',
17
+ backgroundColor: theme.palette.surface.paperBackground,
18
+ }));
19
+
20
+ const TitleContainer = styled(Box)(({ theme }) => ({
21
+ backgroundColor: theme.palette.surface.grey,
22
+ height: '45px',
23
+ display: 'flex',
24
+ alignItems: 'center',
25
+ paddingLeft: '16px',
26
+ }));
27
+
28
+ export const StepperTitle = (props: StepperTitleProps) => {
29
+ return (
30
+ <StepperTitleContainer {...props.contentProps}>
31
+ {props.isShowTitle && (
32
+ <TitleContainer {...props.titleProps}>
33
+ <Typography variant="subtitle3">{props.title}</Typography>
34
+ </TitleContainer>
35
+ )}
36
+ {props.content}
37
+ </StepperTitleContainer>
38
+ );
39
+ };
@@ -2,4 +2,5 @@ export * from './AppHeader/AppHeader';
2
2
  export * from './PageContent/PageContent';
3
3
  export * from './PageHeader/components/DensitySelector/DensitySelector';
4
4
  export * from './PageHeader/PageHeader';
5
+ export * from './StepperTitle/StepperTitle';
5
6
  export * from './TabsLayout/TabsLayout';
@@ -4,6 +4,7 @@ import {
4
4
  IconButton,
5
5
  Stack,
6
6
  styled,
7
+ SxProps,
7
8
  Typography,
8
9
  useTheme,
9
10
  } from '@mui/material';
@@ -15,6 +16,7 @@ export type PreviewFilesProps = {
15
16
  label?: string;
16
17
  onChange?: (newFiles: File[], deletedFile: File) => void;
17
18
  showDownload?: boolean;
19
+ sx?: SxProps;
18
20
  } & Omit<BoxProps, 'onChange'>;
19
21
 
20
22
  export const PreviewFiles = ({
@@ -22,6 +24,7 @@ export const PreviewFiles = ({
22
24
  label,
23
25
  onChange,
24
26
  showDownload,
27
+ sx,
25
28
  ...props
26
29
  }: PreviewFilesProps) => {
27
30
  const theme = useTheme(),
@@ -86,7 +89,7 @@ export const PreviewFiles = ({
86
89
  if (resolvedFiles.length === 0) return <></>;
87
90
 
88
91
  return (
89
- <Box {...props}>
92
+ <Box sx={sx} {...props}>
90
93
  {label && (
91
94
  <Typography
92
95
  marginBottom={'8px'}
@@ -103,12 +106,16 @@ export const PreviewFiles = ({
103
106
  direction={'row'}
104
107
  sx={{ display: 'flex', alignItems: 'center', gap: '12px' }}
105
108
  >
106
- {getFileIcon(file)}
109
+ <Box width={'30px'} height={'30px'}>
110
+ {getFileIcon(file)}
111
+ </Box>
112
+
107
113
  <Stack direction={'column'} marginLeft={'8px'}>
108
114
  <Typography
109
115
  fontSize={'14px'}
110
116
  color={theme.palette.primary.main}
111
117
  variant="label2"
118
+ sx={{ wordBreak: 'break-all' }}
112
119
  >
113
120
  {file.name}
114
121
  </Typography>
@@ -149,7 +156,7 @@ export const PreviewFiles = ({
149
156
 
150
157
  const PreviewContainer = styled(Box)(({ theme }) => ({
151
158
  width: '100%',
152
- height: '60px',
159
+ minHeight: '60px',
153
160
  cursor: 'pointer',
154
161
  backgroundColor: theme.palette.secondary.light,
155
162
  padding: '16px 8px',
@@ -0,0 +1,124 @@
1
+ import { LocalizationProvider } from '@mui/x-date-pickers';
2
+ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3';
3
+ import { Meta, StoryObj } from '@storybook/react';
4
+ import { add } from 'date-fns';
5
+ import { DateTimePicker, Icons } from '../../components/export';
6
+
7
+ const meta: Meta<typeof DateTimePicker> = {
8
+ title: 'Input/DateTimePicker',
9
+ component: DateTimePicker,
10
+ decorators: [
11
+ (Story) => (
12
+ <LocalizationProvider dateAdapter={AdapterDateFns}>
13
+ <Story />
14
+ </LocalizationProvider>
15
+ ),
16
+ ],
17
+ };
18
+
19
+ export default meta;
20
+
21
+ type Story = StoryObj<typeof DateTimePicker>;
22
+
23
+ const shortcutsItems = [
24
+ { label: 'Now', getValue: () => new Date() },
25
+ { label: '1 Hour Later', getValue: () => add(new Date(), { hours: 1 }) },
26
+ { label: '1 Hour Ago', getValue: () => add(new Date(), { hours: -1 }) },
27
+ {
28
+ label: 'New Year',
29
+ getValue: () => new Date(new Date().getFullYear(), 0, 1, 0, 0),
30
+ },
31
+ ];
32
+
33
+ export const Primary: Story = {
34
+ args: {
35
+ label: 'Date Time Picker',
36
+ name: 'date-time-picker',
37
+ placeholder: 'Select Date and Time',
38
+ required: true,
39
+ },
40
+ };
41
+
42
+ export const WithShortcuts: Story = {
43
+ args: {
44
+ ...Primary.args,
45
+ label: 'With Shortcuts',
46
+ shortcutsItems,
47
+ },
48
+ };
49
+
50
+ export const CustomFormat: Story = {
51
+ args: {
52
+ ...Primary.args,
53
+ label: 'Custom Format',
54
+ format: 'MMM dd, yyyy hh:mm a',
55
+ },
56
+ };
57
+
58
+ export const ViewsYearMonth: Story = {
59
+ args: {
60
+ ...Primary.args,
61
+ label: 'Year and Month Views',
62
+ views: ['year', 'month'],
63
+ },
64
+ };
65
+
66
+ export const WithHelperText: Story = {
67
+ args: {
68
+ ...Primary.args,
69
+ label: 'With Helper Text',
70
+ helperText: 'Please select a valid date and time',
71
+ },
72
+ };
73
+
74
+ export const MinMaxDates: Story = {
75
+ args: {
76
+ ...Primary.args,
77
+ label: 'With Min and Max Dates',
78
+ minDate: new Date('2024-01-01'),
79
+ maxDate: new Date('2024-12-31'),
80
+ },
81
+ };
82
+
83
+ export const CustomIcon: Story = {
84
+ args: {
85
+ ...Primary.args,
86
+ label: 'With Custom Icon',
87
+ openPickerIcon: Icons.CareerIcon,
88
+ },
89
+ };
90
+
91
+ export const ReadOnly: Story = {
92
+ args: {
93
+ ...Primary.args,
94
+ label: 'Read Only',
95
+ required: false,
96
+ disabled: true,
97
+ value: new Date('2024-09-15 14:30'),
98
+ },
99
+ };
100
+
101
+ export const DisableFutureDates: Story = {
102
+ args: {
103
+ ...Primary.args,
104
+ label: 'Disable Future Dates',
105
+ disableFuture: true,
106
+ },
107
+ };
108
+
109
+ export const DisablePastDates: Story = {
110
+ args: {
111
+ ...Primary.args,
112
+ label: 'Disable Past Dates',
113
+ disablePast: true,
114
+ },
115
+ };
116
+
117
+ export const DisableSpecificDates: Story = {
118
+ args: {
119
+ ...Primary.args,
120
+ label: 'Disable Weekends',
121
+ shouldDisableDate: (date: Date) =>
122
+ date.getDay() === 0 || date.getDay() === 6,
123
+ },
124
+ };
@@ -334,6 +334,10 @@ export const getCommonTheme = (mode: Theme) => {
334
334
  fontSize: '14px ',
335
335
  fontFamily: 'Poppins',
336
336
  fontWeight: 600,
337
+ '@media (max-width:959.95px)': {
338
+ fontSize: '12px',
339
+ padding: '6px 12px ',
340
+ },
337
341
  '&:hover': {
338
342
  boxShadow: 'none ',
339
343
  '@media (hover: none )': {
@@ -558,6 +562,9 @@ export const getCommonTheme = (mode: Theme) => {
558
562
  minHeight: '50px',
559
563
  paddingBottom: '0px',
560
564
  justifyContent: 'flex-start',
565
+ '@media (max-width:959.95px)': {
566
+ fontSize: '12px',
567
+ },
561
568
  '&.Mui-selected': {
562
569
  color: ColorTokens.text.primary,
563
570
  },