pixel-react 1.6.7 → 1.6.8
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/lib/components/AppHeader/types.d.ts +2 -0
- package/lib/components/Charts/BarChart/BarChart.d.ts +1 -0
- package/lib/components/Charts/DashboardDonutChart/types.d.ts +6 -0
- package/lib/components/FileDropzone/RadioFilePreview.d.ts +4 -0
- package/lib/components/FileDropzone/types.d.ts +61 -0
- package/lib/components/MenuOption/types.d.ts +3 -2
- package/lib/components/Search/Search.d.ts +1 -1
- package/lib/components/Search/types.d.ts +4 -0
- package/lib/components/Table/Types.d.ts +1 -1
- package/lib/components/Tabs/types.d.ts +1 -0
- package/lib/index.d.ts +95 -23
- package/lib/index.esm.js +513 -294
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +514 -293
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/FormatString/FormatString.d.ts +1 -0
- package/package.json +1 -1
- package/src/StyleGuide/ColorPalette/colorPaletteList.ts +15 -0
- package/src/assets/Themes/BaseTheme.scss +5 -3
- package/src/assets/Themes/DarkTheme.scss +5 -3
- package/src/assets/icons/window_maximize.svg +1 -2
- package/src/assets/icons/window_restore.svg +4 -0
- package/src/components/AppHeader/AppHeader.scss +33 -0
- package/src/components/AppHeader/AppHeader.stories.tsx +133 -5
- package/src/components/AppHeader/AppHeader.tsx +111 -112
- package/src/components/AppHeader/types.ts +2 -0
- package/src/components/Charts/BarChart/BarChart.scss +4 -1
- package/src/components/Charts/BarChart/BarChart.tsx +23 -9
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.scss +10 -3
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.stories.tsx +2 -1
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.tsx +54 -25
- package/src/components/Charts/DashboardDonutChart/types.ts +7 -1
- package/src/components/Charts/LineChart/LineChart.scss +13 -9
- package/src/components/Charts/LineChart/LineChart.tsx +6 -2
- package/src/components/DatePicker/DatePicker.scss +11 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +19 -0
- package/src/components/DatePicker/DatePicker.tsx +73 -22
- package/src/components/FileDropzone/Dropzone.tsx +76 -28
- package/src/components/FileDropzone/FileDropzone.scss +30 -2
- package/src/components/FileDropzone/FileDropzone.stories.tsx +125 -4
- package/src/components/FileDropzone/FileDropzone.tsx +46 -13
- package/src/components/FileDropzone/RadioFilePreview.tsx +76 -0
- package/src/components/FileDropzone/types.ts +73 -0
- package/src/components/Icon/iconList.ts +2 -0
- package/src/components/Input/Input.scss +137 -125
- package/src/components/Input/Input.tsx +69 -63
- package/src/components/InputWithDropdown/InputWithDropdown.scss +9 -2
- package/src/components/InputWithDropdown/types.ts +3 -3
- package/src/components/MenuOption/MenuOption.stories.tsx +4 -3
- package/src/components/MenuOption/MenuOption.tsx +1 -1
- package/src/components/MenuOption/types.ts +4 -2
- package/src/components/ModulesChip/ModuleChip.scss +21 -8
- package/src/components/ModulesChip/ModuleChip.stories.tsx +2 -2
- package/src/components/ModulesChip/ModuleChip.tsx +6 -9
- package/src/components/MultiSelect/Dropdown.tsx +12 -5
- package/src/components/MultiSelect/MultiSelect.stories.tsx +12 -9
- package/src/components/MultiSelect/MultiSelect.tsx +10 -9
- package/src/components/PopUpModal/PopUpModal.stories.tsx +1 -1
- package/src/components/Search/Search.stories.tsx +28 -9
- package/src/components/Search/Search.tsx +32 -29
- package/src/components/Search/types.ts +4 -0
- package/src/components/Table/Table.scss +6 -5
- package/src/components/Table/Types.ts +1 -1
- package/src/components/Tabs/Tabs.scss +58 -4
- package/src/components/Tabs/Tabs.stories.tsx +31 -12
- package/src/components/Tabs/Tabs.tsx +27 -18
- package/src/components/Tabs/types.ts +1 -1
- package/src/components/TextArea/Textarea.stories.tsx +1 -1
- package/src/hooks/useFileDropzone.tsx +2 -1
- package/src/index.ts +4 -0
- package/src/utils/FormatString/FormatString.stories.tsx +58 -0
- package/src/utils/FormatString/FormatString.tsx +41 -0
@@ -15,15 +15,19 @@
|
|
15
15
|
transition: cx 0.2s ease, cy 0.2s ease;
|
16
16
|
}
|
17
17
|
}
|
18
|
-
.ff-line-chart-yAxisLabel {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
.ff-line-chart-yAxisLabel-warpper {
|
19
|
+
position: relative;
|
20
|
+
min-width: 20px;
|
21
|
+
height: 100%;
|
22
|
+
.ff-line-chart-yAxisLabel {
|
23
|
+
position: absolute;
|
24
|
+
right: 0;
|
25
|
+
top: 50%;
|
26
|
+
display: flex;
|
27
|
+
white-space: nowrap;
|
28
|
+
transform: rotate(270deg) translateX(60%);
|
29
|
+
transform-origin: right center;
|
30
|
+
}
|
27
31
|
}
|
28
32
|
|
29
33
|
.ff-line-chart-text1 {
|
@@ -130,8 +130,11 @@ const LineChart: React.FC<LineChartProps> = ({
|
|
130
130
|
const xTickInterval = Math.floor(data[0].data.length / 4);
|
131
131
|
|
132
132
|
return (
|
133
|
-
<div className="ff-line-chart-text" style={{ width: width }}>
|
134
|
-
<div
|
133
|
+
<div className="ff-line-chart-text" style={{ width: width + 20 }}>
|
134
|
+
<div
|
135
|
+
className="ff-line-chart-yAxisLabel-warpper"
|
136
|
+
style={{ height: height }}
|
137
|
+
>
|
135
138
|
{' '}
|
136
139
|
<Typography
|
137
140
|
className="ff-line-chart-yAxisLabel"
|
@@ -145,6 +148,7 @@ const LineChart: React.FC<LineChartProps> = ({
|
|
145
148
|
{' '}
|
146
149
|
<svg
|
147
150
|
height={height}
|
151
|
+
width={width}
|
148
152
|
onMouseMove={handleMouseMove}
|
149
153
|
onMouseLeave={handleMouseLeave}
|
150
154
|
className="ff-line-chart-svg"
|
@@ -8,6 +8,8 @@
|
|
8
8
|
--rdp-accent-color: var(--brand-color);
|
9
9
|
--rdp-day-height: 24px;
|
10
10
|
--rdp-day-width: 36px;
|
11
|
+
--rdp-day_button-height: 24px;
|
12
|
+
--rdp-day_button-width: 36px;
|
11
13
|
@include fonts.fontPoppins(12px);
|
12
14
|
--rdp-font-family: 'Poppins', sans-serif;
|
13
15
|
}
|
@@ -157,6 +159,15 @@
|
|
157
159
|
background-color: var(--brand-color);
|
158
160
|
color: var(--primary-button-text-color);
|
159
161
|
}
|
162
|
+
&--disabled {
|
163
|
+
color: var(--text-color-light);
|
164
|
+
cursor: default;
|
165
|
+
|
166
|
+
&.ff-custom-month--selected,
|
167
|
+
&.ff-custom-year--selected {
|
168
|
+
background-color: var(--disable-color);
|
169
|
+
}
|
170
|
+
}
|
160
171
|
}
|
161
172
|
}
|
162
173
|
|
@@ -172,3 +172,22 @@ export const Dateonly: Story = {
|
|
172
172
|
);
|
173
173
|
},
|
174
174
|
};
|
175
|
+
|
176
|
+
export const PastOneYear: Story = {
|
177
|
+
render: (args) => {
|
178
|
+
const [selectedDate, setSelectDate] = useState<Date | undefined>();
|
179
|
+
|
180
|
+
return (
|
181
|
+
<CustomDatePicker
|
182
|
+
{...args}
|
183
|
+
value={selectedDate}
|
184
|
+
onChange={setSelectDate}
|
185
|
+
calendarWidth={240}
|
186
|
+
maxDate={new Date()}
|
187
|
+
minDate={new Date(new Date().setFullYear(new Date().getFullYear() - 1))}
|
188
|
+
dateOnly
|
189
|
+
dateFormat="dd MMM yyyy"
|
190
|
+
/>
|
191
|
+
);
|
192
|
+
},
|
193
|
+
};
|
@@ -217,6 +217,40 @@ const CustomDatePicker: React.FC<DatePickerProps> = ({
|
|
217
217
|
}
|
218
218
|
};
|
219
219
|
|
220
|
+
const isDisabledDate = (
|
221
|
+
year: number | null,
|
222
|
+
month: number | null,
|
223
|
+
minDate?: Date,
|
224
|
+
maxDate?: Date
|
225
|
+
): boolean => {
|
226
|
+
const isMinDateValid = minDate instanceof Date && !isNaN(minDate.getTime());
|
227
|
+
const isMaxDateValid = maxDate instanceof Date && !isNaN(maxDate.getTime());
|
228
|
+
|
229
|
+
if (isMinDateValid) {
|
230
|
+
if (year !== null && year < minDate.getFullYear()) return true;
|
231
|
+
if (
|
232
|
+
year !== null &&
|
233
|
+
month !== null &&
|
234
|
+
year === minDate.getFullYear() &&
|
235
|
+
month < minDate.getMonth()
|
236
|
+
)
|
237
|
+
return true;
|
238
|
+
}
|
239
|
+
|
240
|
+
if (isMaxDateValid) {
|
241
|
+
if (year !== null && year > maxDate.getFullYear()) return true;
|
242
|
+
if (
|
243
|
+
year !== null &&
|
244
|
+
month !== null &&
|
245
|
+
year === maxDate.getFullYear() &&
|
246
|
+
month > maxDate.getMonth()
|
247
|
+
)
|
248
|
+
return true;
|
249
|
+
}
|
250
|
+
|
251
|
+
return false;
|
252
|
+
};
|
253
|
+
|
220
254
|
useEffect(() => {
|
221
255
|
if (isPickerOpen && view === 'years') {
|
222
256
|
const currentYear =
|
@@ -255,17 +289,28 @@ const CustomDatePicker: React.FC<DatePickerProps> = ({
|
|
255
289
|
const CustomMonthGrid: React.FC = () => {
|
256
290
|
return (
|
257
291
|
<div className="ff-custom-month_grid">
|
258
|
-
{months.map((month: string, index: number) =>
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
292
|
+
{months.map((month: string, index: number) => {
|
293
|
+
const isDisabled = isDisabledDate(
|
294
|
+
selectedMonth?.getFullYear() || null,
|
295
|
+
index,
|
296
|
+
minDate,
|
297
|
+
maxDate
|
298
|
+
);
|
299
|
+
|
300
|
+
return (
|
301
|
+
<div
|
302
|
+
key={index}
|
303
|
+
onClick={() => !isDisabled && handleMonthSelect(index)}
|
304
|
+
className={classNames('ff-custom-month', {
|
305
|
+
'ff-custom-month--selected':
|
306
|
+
index === selectedMonth?.getMonth(),
|
307
|
+
'ff-custom-month--disabled': isDisabled,
|
308
|
+
})}
|
309
|
+
>
|
310
|
+
<Typography>{month}</Typography>
|
311
|
+
</div>
|
312
|
+
);
|
313
|
+
})}
|
269
314
|
</div>
|
270
315
|
);
|
271
316
|
};
|
@@ -303,17 +348,23 @@ const CustomDatePicker: React.FC<DatePickerProps> = ({
|
|
303
348
|
const CustomYearGrid: React.FC = () => {
|
304
349
|
return (
|
305
350
|
<div className="ff-custom-year_grid">
|
306
|
-
{years.map((year: number) =>
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
351
|
+
{years.map((year: number) => {
|
352
|
+
const isDisabled = isDisabledDate(year, null, minDate, maxDate);
|
353
|
+
|
354
|
+
return (
|
355
|
+
<div
|
356
|
+
key={year}
|
357
|
+
onClick={() => !isDisabled && handleYearSelect(year)}
|
358
|
+
className={classNames('ff-custom-year', {
|
359
|
+
'ff-custom-year--selected':
|
360
|
+
year === selectedMonth?.getFullYear(),
|
361
|
+
'ff-custom-year--disabled': isDisabled,
|
362
|
+
})}
|
363
|
+
>
|
364
|
+
<Typography>{year}</Typography>
|
365
|
+
</div>
|
366
|
+
);
|
367
|
+
})}
|
317
368
|
</div>
|
318
369
|
);
|
319
370
|
};
|
@@ -4,6 +4,8 @@ import './FileDropzone.scss';
|
|
4
4
|
import { DroppableProps } from './types';
|
5
5
|
import Button from '../Button';
|
6
6
|
import Typography from '../Typography';
|
7
|
+
import RadioGroup from '../RadioGroup';
|
8
|
+
import RadioFilePreview from './RadioFilePreview';
|
7
9
|
|
8
10
|
const Dropzone: FC<DroppableProps> = ({
|
9
11
|
icon,
|
@@ -14,42 +16,88 @@ const Dropzone: FC<DroppableProps> = ({
|
|
14
16
|
getInputProps,
|
15
17
|
isDragActive = false,
|
16
18
|
height = 188,
|
19
|
+
isWebServiceFileDropZone = false,
|
20
|
+
selectedRadioOption,
|
21
|
+
radioOptions,
|
22
|
+
handleOptionChange,
|
23
|
+
selectedFile,
|
24
|
+
setSelectedFile,
|
25
|
+
handleRemoveFile,
|
26
|
+
isDisable,
|
17
27
|
}) => {
|
28
|
+
const isWebServiceFile = selectedFile?.name && isWebServiceFileDropZone;
|
18
29
|
return (
|
19
30
|
<div
|
20
31
|
{...getRootProps()}
|
21
32
|
className={classNames('ff-file-dropzone', {
|
22
33
|
'ff-file-dropzone--active': isDragActive,
|
34
|
+
'ff-file-dropzone--webservice-file': isWebServiceFile,
|
35
|
+
'ff-file-dropzone--webservice-container': isWebServiceFileDropZone,
|
23
36
|
})}
|
24
|
-
style={{height: height}}
|
37
|
+
style={{ height: height }}
|
25
38
|
>
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
{
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
{isWebServiceFile ? (
|
40
|
+
<RadioFilePreview
|
41
|
+
selectedFile={selectedFile.name}
|
42
|
+
onFileRemoveClick={handleRemoveFile}
|
43
|
+
onFileReplaceClick={setSelectedFile}
|
44
|
+
setSelectedFile={setSelectedFile}
|
45
|
+
/>
|
46
|
+
) : (
|
47
|
+
<>
|
48
|
+
<div className="ff-file-dropzone-content__icon">{icon}</div>
|
49
|
+
<div className="ff-file-dropzone-content__labels">
|
50
|
+
<Typography
|
51
|
+
as="p"
|
52
|
+
fontWeight="semi-bold"
|
53
|
+
lineHeight="18px"
|
54
|
+
textAlign="center"
|
55
|
+
color={'var(--text-color)'}
|
56
|
+
>
|
57
|
+
{primaryLabel}
|
58
|
+
</Typography>
|
59
|
+
<Typography
|
60
|
+
as="p"
|
61
|
+
lineHeight="18px"
|
62
|
+
textAlign="center"
|
63
|
+
color={'var(--text-color)'}
|
64
|
+
>
|
65
|
+
{secondaryLabel}
|
66
|
+
</Typography>
|
67
|
+
{isWebServiceFileDropZone ? (
|
68
|
+
<div className="ff-radio-group-wrapper">
|
69
|
+
<Typography fontWeight="semi-bold">
|
70
|
+
{' '}
|
71
|
+
Choose file from{' '}
|
72
|
+
</Typography>
|
73
|
+
<RadioGroup
|
74
|
+
name="radio_btn_file_dropzone"
|
75
|
+
options={
|
76
|
+
radioOptions ?? [
|
77
|
+
{ label: 'Default Label', value: 'default_value' },
|
78
|
+
]
|
79
|
+
}
|
80
|
+
selectedValue={selectedRadioOption?.value}
|
81
|
+
onChange={handleOptionChange}
|
82
|
+
/>
|
83
|
+
</div>
|
84
|
+
) : (
|
85
|
+
<Button
|
86
|
+
variant="primary"
|
87
|
+
label={buttonLabel}
|
88
|
+
className='choose-file-btn'
|
89
|
+
disabled={isDisable}
|
90
|
+
>
|
91
|
+
<input
|
92
|
+
{...(isDisable
|
93
|
+
? { style: { cursor: 'not-allowed' }, disabled: true }
|
94
|
+
: getInputProps())}
|
95
|
+
/>
|
96
|
+
</Button>
|
97
|
+
)}
|
98
|
+
</div>
|
99
|
+
</>
|
100
|
+
)}
|
53
101
|
</div>
|
54
102
|
);
|
55
103
|
};
|
@@ -30,11 +30,22 @@
|
|
30
30
|
gap: 8px;
|
31
31
|
transition: background-color 0.2s ease;
|
32
32
|
|
33
|
+
.ff-radio-group-wrapper {
|
34
|
+
position: relative;
|
35
|
+
bottom: 8px;
|
36
|
+
}
|
37
|
+
|
33
38
|
&:hover,
|
34
39
|
&--active {
|
35
40
|
background-color: var(--file-dropzone-selected-color);
|
36
41
|
}
|
37
|
-
|
42
|
+
&--webservice-file {
|
43
|
+
@include center;
|
44
|
+
}
|
45
|
+
&--webservice-container {
|
46
|
+
@include center;
|
47
|
+
padding: 16px 0 40px 0;
|
48
|
+
}
|
38
49
|
&-content {
|
39
50
|
&__icon {
|
40
51
|
height: 80px;
|
@@ -60,6 +71,9 @@
|
|
60
71
|
}
|
61
72
|
}
|
62
73
|
}
|
74
|
+
&__webservice-file {
|
75
|
+
padding: 4px;
|
76
|
+
}
|
63
77
|
}
|
64
78
|
}
|
65
79
|
|
@@ -69,7 +83,6 @@
|
|
69
83
|
overflow-y: auto;
|
70
84
|
scroll-behavior: smooth;
|
71
85
|
padding: 2px;
|
72
|
-
|
73
86
|
::-webkit-scrollbar {
|
74
87
|
width: 2px;
|
75
88
|
}
|
@@ -133,3 +146,18 @@
|
|
133
146
|
}
|
134
147
|
}
|
135
148
|
}
|
149
|
+
.ff-webservice-file-wrapper {
|
150
|
+
display: flex;
|
151
|
+
gap: 8px;
|
152
|
+
.ff-webservice-file-name {
|
153
|
+
position: relative;
|
154
|
+
bottom: 2px;
|
155
|
+
}
|
156
|
+
}
|
157
|
+
.ff-input-ref {
|
158
|
+
display: none;
|
159
|
+
}
|
160
|
+
.ff-disable-file-dropzone-wrapper {
|
161
|
+
opacity: 0.5;
|
162
|
+
cursor: not-allowed;
|
163
|
+
}
|
@@ -1,8 +1,12 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
2
2
|
import { StoryObj, Meta } from '@storybook/react';
|
3
3
|
import FileDropzone from './FileDropzone';
|
4
4
|
import Toaster from '../Toast';
|
5
5
|
import { useState } from 'react';
|
6
|
+
import { RadioOption } from './types';
|
7
|
+
import Drawer from '../Drawer/Drawer';
|
8
|
+
import Typography from '../Typography';
|
9
|
+
import './FileDropzone.scss';
|
6
10
|
|
7
11
|
const meta: Meta<typeof FileDropzone> = {
|
8
12
|
title: 'Components/FileDropzone',
|
@@ -59,13 +63,13 @@ export const Controlled: Story = {
|
|
59
63
|
}, 2000);
|
60
64
|
};
|
61
65
|
|
62
|
-
const getAcceptedFiles = (files) => {
|
66
|
+
const getAcceptedFiles = (files) => {
|
63
67
|
setAcceptedFiles(files);
|
64
|
-
}
|
68
|
+
};
|
65
69
|
|
66
70
|
const getRejectedFiles = (files) => {
|
67
71
|
setRejectedFiles(files);
|
68
|
-
}
|
72
|
+
};
|
69
73
|
|
70
74
|
return (
|
71
75
|
<>
|
@@ -81,6 +85,103 @@ export const Controlled: Story = {
|
|
81
85
|
onMaxFilesError={showMaxFilesError}
|
82
86
|
getAcceptedFiles={getAcceptedFiles}
|
83
87
|
getRejectedFiles={getRejectedFiles}
|
88
|
+
isApiResponseError
|
89
|
+
/>
|
90
|
+
{showToaster && (
|
91
|
+
<Toaster
|
92
|
+
isOpen={showToaster}
|
93
|
+
variant="danger"
|
94
|
+
toastTitle="Error"
|
95
|
+
toastMessage={'Max 5 files can be uploaded'}
|
96
|
+
/>
|
97
|
+
)}
|
98
|
+
</>
|
99
|
+
);
|
100
|
+
},
|
101
|
+
};
|
102
|
+
|
103
|
+
export const WithRadioButton: Story = {
|
104
|
+
render: () => {
|
105
|
+
const [showToaster, setShowToaster] = useState<boolean>(false);
|
106
|
+
const [showModal, setShowModal] = useState(false);
|
107
|
+
|
108
|
+
const [selectedRadioOption, setSelectedRadioOption] =
|
109
|
+
useState<RadioOption>();
|
110
|
+
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
111
|
+
|
112
|
+
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
113
|
+
|
114
|
+
const drawerArgs = {
|
115
|
+
primaryButtonProps: {
|
116
|
+
label: 'Create',
|
117
|
+
variant: 'primary',
|
118
|
+
disabled: false,
|
119
|
+
onClick: () => {},
|
120
|
+
},
|
121
|
+
secondaryButtonProps: {
|
122
|
+
label: 'Cancel',
|
123
|
+
variant: 'secondary',
|
124
|
+
disabled: false,
|
125
|
+
onClick: () => {},
|
126
|
+
},
|
127
|
+
};
|
128
|
+
|
129
|
+
useEffect(() => {
|
130
|
+
if (selectedRadioOption?.value === 'Local File' && fileInputRef.current) {
|
131
|
+
fileInputRef.current.click();
|
132
|
+
}
|
133
|
+
}, [selectedRadioOption]);
|
134
|
+
|
135
|
+
const radioOptions: RadioOption[] = [
|
136
|
+
{ value: 'Test Data', label: 'Test Data' },
|
137
|
+
{ value: 'Local File', label: 'Local File' },
|
138
|
+
];
|
139
|
+
const handleOptionChange = (option: RadioOption) => {
|
140
|
+
setSelectedRadioOption(option);
|
141
|
+
if (option.value === 'Test Data') {
|
142
|
+
setShowModal(true);
|
143
|
+
} else {
|
144
|
+
setShowModal(false);
|
145
|
+
}
|
146
|
+
};
|
147
|
+
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
148
|
+
const file = event.target.files?.[0];
|
149
|
+
if (file) {
|
150
|
+
setSelectedFile(file);
|
151
|
+
}
|
152
|
+
};
|
153
|
+
|
154
|
+
const handleRemoveFile = () => {
|
155
|
+
setSelectedFile(null);
|
156
|
+
};
|
157
|
+
|
158
|
+
const showMaxFilesError = () => {
|
159
|
+
setShowToaster(true);
|
160
|
+
setTimeout(() => {
|
161
|
+
setShowToaster(false);
|
162
|
+
}, 2000);
|
163
|
+
};
|
164
|
+
|
165
|
+
return (
|
166
|
+
<>
|
167
|
+
<FileDropzone
|
168
|
+
{...defaultArgs}
|
169
|
+
accept={[
|
170
|
+
'image/png',
|
171
|
+
'image/jpeg',
|
172
|
+
'application/x-zip-compressed',
|
173
|
+
'application/zip',
|
174
|
+
]}
|
175
|
+
validateMIMEType={true}
|
176
|
+
onMaxFilesError={showMaxFilesError}
|
177
|
+
isWebServiceFileDropZone
|
178
|
+
selectedRadioOption={selectedRadioOption}
|
179
|
+
radioOptions={radioOptions}
|
180
|
+
handleOptionChange={handleOptionChange}
|
181
|
+
setSelectedFile={setSelectedFile}
|
182
|
+
selectedFile={selectedFile}
|
183
|
+
handleFileChange={handleFileChange}
|
184
|
+
handleRemoveFile={handleRemoveFile}
|
84
185
|
/>
|
85
186
|
{showToaster && (
|
86
187
|
<Toaster
|
@@ -90,6 +191,26 @@ export const Controlled: Story = {
|
|
90
191
|
toastMessage={'Max 5 files can be uploaded'}
|
91
192
|
/>
|
92
193
|
)}
|
194
|
+
{selectedRadioOption?.value === 'Local File' ? (
|
195
|
+
<input
|
196
|
+
ref={fileInputRef}
|
197
|
+
type="file"
|
198
|
+
className='ff-input-ref'
|
199
|
+
onChange={handleFileChange}
|
200
|
+
accept="image/png, image/jpeg, application/x-zip-compressed, application/zip"
|
201
|
+
/>
|
202
|
+
) : (
|
203
|
+
<Drawer
|
204
|
+
{...drawerArgs}
|
205
|
+
isOpen={showModal}
|
206
|
+
onClose={() => setShowModal(false)}
|
207
|
+
isFooterRequired={true}
|
208
|
+
_isExpanded={false}
|
209
|
+
size="small"
|
210
|
+
>
|
211
|
+
<Typography>Upload TestData Files Here</Typography>
|
212
|
+
</Drawer>
|
213
|
+
)}
|
93
214
|
</>
|
94
215
|
);
|
95
216
|
},
|
@@ -3,9 +3,10 @@ import { FileDropzoneProps } from './types';
|
|
3
3
|
import './FileDropzone.scss';
|
4
4
|
import Icon from '../Icon';
|
5
5
|
import { checkEmpty } from '../../utils/checkEmpty/checkEmpty';
|
6
|
-
import { useMemo } from 'react';
|
6
|
+
import { useEffect, useMemo } from 'react';
|
7
7
|
import Dropzone from './Dropzone';
|
8
8
|
import FilePreview from './FilePreview';
|
9
|
+
import classNames from 'classnames';
|
9
10
|
|
10
11
|
const FileDropzone: React.FC<FileDropzoneProps> = ({
|
11
12
|
icon = (
|
@@ -27,6 +28,16 @@ const FileDropzone: React.FC<FileDropzoneProps> = ({
|
|
27
28
|
height = 188,
|
28
29
|
getAcceptedFiles = () => {},
|
29
30
|
getRejectedFiles = () => {},
|
31
|
+
isWebServiceFileDropZone = false,
|
32
|
+
selectedRadioOption,
|
33
|
+
radioOptions,
|
34
|
+
handleOptionChange,
|
35
|
+
selectedFile,
|
36
|
+
setSelectedFile,
|
37
|
+
handleFileChange,
|
38
|
+
handleRemoveFile,
|
39
|
+
isApiResponseError = false,
|
40
|
+
isDisable = false,
|
30
41
|
}) => {
|
31
42
|
const {
|
32
43
|
getRootProps,
|
@@ -46,6 +57,7 @@ const FileDropzone: React.FC<FileDropzoneProps> = ({
|
|
46
57
|
invalidFileMessage,
|
47
58
|
fileExistMessage,
|
48
59
|
validateMIMEType,
|
60
|
+
isApiResponseError,
|
49
61
|
// onDrop: (accepted, rejected, event) => {}, //onDrop function to handle dropped or selected files explicitly.
|
50
62
|
});
|
51
63
|
|
@@ -65,6 +77,12 @@ const FileDropzone: React.FC<FileDropzoneProps> = ({
|
|
65
77
|
[acceptedFiles, handleRemoveClick, handleReplaceClick]
|
66
78
|
);
|
67
79
|
|
80
|
+
useEffect(() => {
|
81
|
+
if (!checkEmpty(acceptedFiles) && setSelectedFile) {
|
82
|
+
setSelectedFile(acceptedFiles[0] || null);
|
83
|
+
}
|
84
|
+
}, [acceptedFiles, setSelectedFile]);
|
85
|
+
|
68
86
|
const rejectedFilesList = useMemo(
|
69
87
|
() =>
|
70
88
|
rejectedFiles.map((rejectedFile) => (
|
@@ -80,7 +98,9 @@ const FileDropzone: React.FC<FileDropzoneProps> = ({
|
|
80
98
|
);
|
81
99
|
|
82
100
|
return (
|
83
|
-
<div className=
|
101
|
+
<div className={classNames('ff-file-dropzone-wrapper',
|
102
|
+
{'ff-disable-file-dropzone-wrapper': isDisable,}
|
103
|
+
)} style={{ width: `${width}px` }}>
|
84
104
|
<Dropzone
|
85
105
|
icon={icon}
|
86
106
|
primaryLabel={primaryLabel}
|
@@ -90,20 +110,33 @@ const FileDropzone: React.FC<FileDropzoneProps> = ({
|
|
90
110
|
getInputProps={getInputProps}
|
91
111
|
isDragActive={isDragActive}
|
92
112
|
height={`${height}px`}
|
113
|
+
isWebServiceFileDropZone={isWebServiceFileDropZone}
|
114
|
+
selectedRadioOption={selectedRadioOption}
|
115
|
+
radioOptions={
|
116
|
+
radioOptions ?? [{ label: 'Default Label', value: 'default_value' }]
|
117
|
+
}
|
118
|
+
handleOptionChange={handleOptionChange}
|
119
|
+
selectedFile={selectedFile}
|
120
|
+
handleFileChange={handleFileChange}
|
121
|
+
handleRemoveFile={handleRemoveFile}
|
122
|
+
setSelectedFile={setSelectedFile}
|
123
|
+
isDisable={isDisable}
|
93
124
|
/>
|
94
125
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
126
|
+
{isWebServiceFileDropZone ? null : (
|
127
|
+
<div
|
128
|
+
className={'ff-file-details-wrapper'}
|
129
|
+
style={{ width: `${width}px` }}
|
130
|
+
>
|
131
|
+
{!checkEmpty(acceptedFiles) && (
|
132
|
+
<div className="ff-file-details">{acceptedFilesList}</div>
|
133
|
+
)}
|
102
134
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
135
|
+
{!checkEmpty(rejectedFiles) && (
|
136
|
+
<div className="ff-file-details">{rejectedFilesList}</div>
|
137
|
+
)}
|
138
|
+
</div>
|
139
|
+
)}
|
107
140
|
</div>
|
108
141
|
);
|
109
142
|
};
|