@visns-studio/visns-components 5.5.1 → 5.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -5
- package/src/components/crm/DataGrid.jsx +357 -15
- package/src/components/crm/MultiSelect.jsx +19 -2
- package/src/components/crm/generic/GenericReport.jsx +1426 -330
- package/src/components/crm/generic/styles/GenericReport.module.scss +140 -23
- package/src/components/crm/generic/styles/SweetAlertCustom.css +85 -0
- package/src/components/crm/styles/DataGrid.module.scss +468 -13
- package/src/components/styles/global.css +138 -0
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"@nivo/line": "^0.88.0",
|
|
10
10
|
"@nivo/pie": "^0.88.0",
|
|
11
11
|
"@tinymce/tinymce-react": "^6.1.0",
|
|
12
|
-
"@vitejs/plugin-react": "^4.
|
|
12
|
+
"@vitejs/plugin-react": "^4.4.0",
|
|
13
13
|
"add": "^2.0.6",
|
|
14
14
|
"akar-icons": "^1.9.31",
|
|
15
15
|
"array-move": "^4.0.0",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"axios": "^1.8.4",
|
|
18
18
|
"browser-image-compression": "^2.0.2",
|
|
19
19
|
"dayjs": "^1.11.13",
|
|
20
|
-
"fabric": "^6.6.
|
|
20
|
+
"fabric": "^6.6.4",
|
|
21
21
|
"file-saver": "^2.0.5",
|
|
22
22
|
"framer-motion": "^11.18.2",
|
|
23
23
|
"html-react-parser": "^5.2.3",
|
|
@@ -54,12 +54,13 @@
|
|
|
54
54
|
"reactjs-popup": "^2.0.6",
|
|
55
55
|
"style-loader": "^4.0.0",
|
|
56
56
|
"swapy": "^1.0.5",
|
|
57
|
-
"sweetalert2": "^11.
|
|
57
|
+
"sweetalert2": "^11.19.1",
|
|
58
58
|
"truncate": "^3.0.0",
|
|
59
59
|
"uuid": "^10.0.0",
|
|
60
60
|
"validator": "^13.15.0",
|
|
61
61
|
"vite": "^5.4.18",
|
|
62
|
-
"yarn": "^1.22.22"
|
|
62
|
+
"yarn": "^1.22.22",
|
|
63
|
+
"yet-another-react-lightbox": "^3.22.0"
|
|
63
64
|
},
|
|
64
65
|
"devDependencies": {
|
|
65
66
|
"@babel/core": "^7.26.10",
|
|
@@ -81,7 +82,7 @@
|
|
|
81
82
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
82
83
|
},
|
|
83
84
|
"name": "@visns-studio/visns-components",
|
|
84
|
-
"version": "5.5.
|
|
85
|
+
"version": "5.5.3",
|
|
85
86
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
86
87
|
"main": "src/index.js",
|
|
87
88
|
"files": [
|
|
@@ -16,6 +16,7 @@ import numeral from 'numeral';
|
|
|
16
16
|
import Popup from 'reactjs-popup';
|
|
17
17
|
import 'reactjs-popup/dist/index.css';
|
|
18
18
|
import parse from 'html-react-parser';
|
|
19
|
+
import 'react-toggle/style.css';
|
|
19
20
|
import { saveAs } from 'file-saver';
|
|
20
21
|
import NumberFilter from '@inovua/reactdatagrid-community/NumberFilter';
|
|
21
22
|
import SelectFilter from '@inovua/reactdatagrid-community/SelectFilter';
|
|
@@ -25,9 +26,12 @@ import ReactDataGrid from '@inovua/reactdatagrid-community';
|
|
|
25
26
|
// import SelectFilter from '@visns-studio/visns-datagrid-enterprise/SelectFilter';
|
|
26
27
|
// import DateFilter from '@visns-studio/visns-datagrid-enterprise/DateFilter';
|
|
27
28
|
// import ReactDataGrid from '@visns-studio/visns-datagrid-enterprise';
|
|
28
|
-
import { Gallery } from 'react-grid-gallery';
|
|
29
|
+
// import { Gallery } from 'react-grid-gallery';
|
|
29
30
|
import { confirmAlert } from 'react-confirm-alert';
|
|
30
31
|
import { toast } from 'react-toastify';
|
|
32
|
+
import imageCompression from 'browser-image-compression';
|
|
33
|
+
import Vapor from 'laravel-vapor';
|
|
34
|
+
import Lightbox from 'yet-another-react-lightbox';
|
|
31
35
|
import {
|
|
32
36
|
Alarm,
|
|
33
37
|
ArrowCounterClockwise,
|
|
@@ -59,6 +63,7 @@ import styles from './styles/DataGrid.module.scss';
|
|
|
59
63
|
|
|
60
64
|
import '@inovua/reactdatagrid-community/index.css';
|
|
61
65
|
import 'react-confirm-alert/src/react-confirm-alert.css';
|
|
66
|
+
import 'yet-another-react-lightbox/styles.css';
|
|
62
67
|
|
|
63
68
|
import CustomFetch from './Fetch';
|
|
64
69
|
import Download from './Download';
|
|
@@ -166,6 +171,13 @@ const DataGrid = forwardRef(
|
|
|
166
171
|
/** Gallery Modal States */
|
|
167
172
|
const [modalGalleryShow, setModalGalleryShow] = useState(false);
|
|
168
173
|
const [galleryData, setGalleryData] = useState([]);
|
|
174
|
+
const [uploadProgress, setUploadProgress] = useState(0);
|
|
175
|
+
const [currentItem, setCurrentItem] = useState(null);
|
|
176
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
177
|
+
|
|
178
|
+
/** Lightbox States */
|
|
179
|
+
const [lightboxOpen, setLightboxOpen] = useState(false);
|
|
180
|
+
const [lightboxIndex, setLightboxIndex] = useState(0);
|
|
169
181
|
|
|
170
182
|
/** Gallery Modal Functions */
|
|
171
183
|
const modalGalleryOpen = () => {
|
|
@@ -176,6 +188,149 @@ const DataGrid = forwardRef(
|
|
|
176
188
|
setModalGalleryShow(false);
|
|
177
189
|
};
|
|
178
190
|
|
|
191
|
+
const handleFileUpload = async (files) => {
|
|
192
|
+
if (!currentItem || !currentItem.settings.upload) return;
|
|
193
|
+
|
|
194
|
+
setIsUploading(true);
|
|
195
|
+
const uploadPromises = [];
|
|
196
|
+
|
|
197
|
+
for (let i = 0; i < files.length; i++) {
|
|
198
|
+
const file = files[i];
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
// Optimize image if needed
|
|
202
|
+
let optimizedFile = file;
|
|
203
|
+
if (file.type.startsWith('image/')) {
|
|
204
|
+
const options = {
|
|
205
|
+
maxSizeMB: 1,
|
|
206
|
+
maxWidthOrHeight: 1920,
|
|
207
|
+
useWebWorker: true,
|
|
208
|
+
};
|
|
209
|
+
try {
|
|
210
|
+
optimizedFile = await imageCompression(
|
|
211
|
+
file,
|
|
212
|
+
options
|
|
213
|
+
);
|
|
214
|
+
} catch (err) {
|
|
215
|
+
console.error('Image compression failed:', err);
|
|
216
|
+
// Continue with original file if compression fails
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Upload to Vapor
|
|
221
|
+
const uploadPromise = new Promise((resolve, reject) => {
|
|
222
|
+
Vapor.store(optimizedFile, {
|
|
223
|
+
progress: (progress) => {
|
|
224
|
+
setUploadProgress(progress * 100);
|
|
225
|
+
},
|
|
226
|
+
})
|
|
227
|
+
.then((response) => {
|
|
228
|
+
// Construct the URL with the key parameter
|
|
229
|
+
const uploadSettings =
|
|
230
|
+
currentItem.settings.upload;
|
|
231
|
+
const itemData = currentItem.data;
|
|
232
|
+
const keyValue = itemData[uploadSettings.key];
|
|
233
|
+
const url = keyValue
|
|
234
|
+
? `${uploadSettings.url}/${keyValue}`
|
|
235
|
+
: uploadSettings.url;
|
|
236
|
+
|
|
237
|
+
// Make the PUT request
|
|
238
|
+
CustomFetch(
|
|
239
|
+
url,
|
|
240
|
+
uploadSettings.method || 'POST',
|
|
241
|
+
{
|
|
242
|
+
uuid: response.uuid,
|
|
243
|
+
key: response.key,
|
|
244
|
+
bucket: response.bucket,
|
|
245
|
+
filename: file.name,
|
|
246
|
+
filesize: optimizedFile.size,
|
|
247
|
+
extension: response.extension,
|
|
248
|
+
file_relationship: uploadSettings.id,
|
|
249
|
+
},
|
|
250
|
+
(result) => {
|
|
251
|
+
if (result.error === '') {
|
|
252
|
+
resolve();
|
|
253
|
+
} else {
|
|
254
|
+
toast.error(String(result.error));
|
|
255
|
+
reject(result.error);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
})
|
|
260
|
+
.catch(reject);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
uploadPromises.push(uploadPromise);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error('Error uploading file:', error);
|
|
266
|
+
toast.error(
|
|
267
|
+
`Error uploading ${file.name}: ${
|
|
268
|
+
error.message || 'Unknown error'
|
|
269
|
+
}`
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
await Promise.all(uploadPromises);
|
|
276
|
+
toast.success('Files uploaded successfully');
|
|
277
|
+
|
|
278
|
+
// Refresh the gallery data
|
|
279
|
+
if (currentItem && currentItem.settings && currentItem.data) {
|
|
280
|
+
const s = currentItem.settings;
|
|
281
|
+
const d = currentItem.data;
|
|
282
|
+
|
|
283
|
+
// Function to access nested property using a series of keys
|
|
284
|
+
const getNestedValue = (data, keys) =>
|
|
285
|
+
keys.reduce(
|
|
286
|
+
(currentValue, key) =>
|
|
287
|
+
currentValue && currentValue[key] !== undefined
|
|
288
|
+
? currentValue[key]
|
|
289
|
+
: undefined,
|
|
290
|
+
data
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
// Fetch updated data
|
|
294
|
+
try {
|
|
295
|
+
const res = await CustomFetch(
|
|
296
|
+
`${form.url}/${d[form.primaryKey]}`,
|
|
297
|
+
'GET',
|
|
298
|
+
{}
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
if (res.data) {
|
|
302
|
+
// Extract the updated nested value
|
|
303
|
+
const updatedNestedValue = getNestedValue(
|
|
304
|
+
res.data,
|
|
305
|
+
s.relation
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
// Update gallery data
|
|
309
|
+
if (
|
|
310
|
+
updatedNestedValue &&
|
|
311
|
+
Array.isArray(updatedNestedValue)
|
|
312
|
+
) {
|
|
313
|
+
const updatedGalleryArray =
|
|
314
|
+
updatedNestedValue.map((item) => ({
|
|
315
|
+
src: item[s.key],
|
|
316
|
+
caption: item.file_name,
|
|
317
|
+
}));
|
|
318
|
+
|
|
319
|
+
setGalleryData(updatedGalleryArray);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
} catch (error) {
|
|
323
|
+
console.error('Error refreshing gallery data:', error);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.error('Error in upload process:', error);
|
|
328
|
+
} finally {
|
|
329
|
+
setIsUploading(false);
|
|
330
|
+
setUploadProgress(0);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
179
334
|
/** Modal States */
|
|
180
335
|
const [formData, setFormData] = useState({});
|
|
181
336
|
const [formType, setFormType] = useState('');
|
|
@@ -601,13 +756,16 @@ const DataGrid = forwardRef(
|
|
|
601
756
|
// Extracting nested value using predefined keys from 's.relation'
|
|
602
757
|
const nestedValue = getNestedValue(d, s.relation);
|
|
603
758
|
|
|
604
|
-
// Mapping nested values to create gallery array with source and
|
|
759
|
+
// Mapping nested values to create gallery array with source, captions, and dimensions
|
|
605
760
|
const galleryArray = nestedValue.map((item) => ({
|
|
606
761
|
src: item[s.key],
|
|
607
762
|
caption: item.file_name,
|
|
763
|
+
width: 320, // Default width for proper grid layout
|
|
764
|
+
height: 240, // Default height for proper grid layout
|
|
608
765
|
}));
|
|
609
766
|
|
|
610
767
|
setGalleryData(galleryArray);
|
|
768
|
+
setCurrentItem({ data: d, settings: s });
|
|
611
769
|
|
|
612
770
|
modalGalleryOpen();
|
|
613
771
|
break;
|
|
@@ -2461,11 +2619,9 @@ const DataGrid = forwardRef(
|
|
|
2461
2619
|
if (shouldRenderButton) {
|
|
2462
2620
|
return (
|
|
2463
2621
|
<button
|
|
2464
|
-
className={
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
'0.2em 1em 0.05em 1em',
|
|
2468
|
-
}}
|
|
2622
|
+
className={
|
|
2623
|
+
styles.clockButton
|
|
2624
|
+
}
|
|
2469
2625
|
onClick={(e) => {
|
|
2470
2626
|
e.stopPropagation();
|
|
2471
2627
|
e.preventDefault();
|
|
@@ -2497,9 +2653,9 @@ const DataGrid = forwardRef(
|
|
|
2497
2653
|
data-tooltip-content={`${column.label} Timer`}
|
|
2498
2654
|
strokeWidth={2}
|
|
2499
2655
|
size={18}
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
}
|
|
2656
|
+
style={{
|
|
2657
|
+
color: 'white',
|
|
2658
|
+
}}
|
|
2503
2659
|
/>
|
|
2504
2660
|
</button>
|
|
2505
2661
|
);
|
|
@@ -2983,6 +3139,8 @@ const DataGrid = forwardRef(
|
|
|
2983
3139
|
open={modalGalleryShow}
|
|
2984
3140
|
onClose={modalGalleryClose}
|
|
2985
3141
|
closeOnDocumentClick={false}
|
|
3142
|
+
contentStyle={{ width: 'auto', maxWidth: '90vw' }}
|
|
3143
|
+
overlayStyle={{ background: 'rgba(0, 0, 0, 0.7)' }}
|
|
2986
3144
|
>
|
|
2987
3145
|
<div
|
|
2988
3146
|
className={`${styles.modalwrap} ${styles['top--modal']}`}
|
|
@@ -2997,15 +3155,191 @@ const DataGrid = forwardRef(
|
|
|
2997
3155
|
<CircleX strokeWidth={1} size={24} />
|
|
2998
3156
|
</button>
|
|
2999
3157
|
</div>
|
|
3000
|
-
<div
|
|
3158
|
+
<div
|
|
3159
|
+
className={`${styles.modal__content} ${styles['modal__content--gallery']}`}
|
|
3160
|
+
>
|
|
3161
|
+
{currentItem?.settings?.upload && (
|
|
3162
|
+
<div className={styles.uploadSection}>
|
|
3163
|
+
<h3>
|
|
3164
|
+
<Image
|
|
3165
|
+
strokeWidth={1.5}
|
|
3166
|
+
size={18}
|
|
3167
|
+
/>
|
|
3168
|
+
Upload New Images
|
|
3169
|
+
</h3>
|
|
3170
|
+
<div
|
|
3171
|
+
className={styles.dropzoneContainer}
|
|
3172
|
+
>
|
|
3173
|
+
{isUploading && (
|
|
3174
|
+
<div
|
|
3175
|
+
className={
|
|
3176
|
+
styles.progressBar
|
|
3177
|
+
}
|
|
3178
|
+
>
|
|
3179
|
+
<div
|
|
3180
|
+
className={
|
|
3181
|
+
styles.progressBarInner
|
|
3182
|
+
}
|
|
3183
|
+
style={{
|
|
3184
|
+
width: `${uploadProgress}%`,
|
|
3185
|
+
}}
|
|
3186
|
+
></div>
|
|
3187
|
+
</div>
|
|
3188
|
+
)}
|
|
3189
|
+
<div
|
|
3190
|
+
className={styles.dropzone}
|
|
3191
|
+
onClick={() =>
|
|
3192
|
+
document
|
|
3193
|
+
.getElementById(
|
|
3194
|
+
'gallery-file-upload'
|
|
3195
|
+
)
|
|
3196
|
+
.click()
|
|
3197
|
+
}
|
|
3198
|
+
onDragOver={(e) => {
|
|
3199
|
+
e.preventDefault();
|
|
3200
|
+
e.stopPropagation();
|
|
3201
|
+
}}
|
|
3202
|
+
onDragEnter={(e) => {
|
|
3203
|
+
e.preventDefault();
|
|
3204
|
+
e.stopPropagation();
|
|
3205
|
+
}}
|
|
3206
|
+
onDragLeave={(e) => {
|
|
3207
|
+
e.preventDefault();
|
|
3208
|
+
e.stopPropagation();
|
|
3209
|
+
}}
|
|
3210
|
+
onDrop={(e) => {
|
|
3211
|
+
e.preventDefault();
|
|
3212
|
+
e.stopPropagation();
|
|
3213
|
+
const files =
|
|
3214
|
+
e.dataTransfer.files;
|
|
3215
|
+
if (files.length > 0) {
|
|
3216
|
+
handleFileUpload(files);
|
|
3217
|
+
}
|
|
3218
|
+
}}
|
|
3219
|
+
>
|
|
3220
|
+
<CloudUpload
|
|
3221
|
+
strokeWidth={1.5}
|
|
3222
|
+
size={24}
|
|
3223
|
+
/>
|
|
3224
|
+
<p>
|
|
3225
|
+
Drag and drop files here or
|
|
3226
|
+
click to select files
|
|
3227
|
+
</p>
|
|
3228
|
+
<input
|
|
3229
|
+
id="gallery-file-upload"
|
|
3230
|
+
type="file"
|
|
3231
|
+
multiple
|
|
3232
|
+
style={{ display: 'none' }}
|
|
3233
|
+
onChange={(e) => {
|
|
3234
|
+
if (
|
|
3235
|
+
e.target.files
|
|
3236
|
+
.length > 0
|
|
3237
|
+
) {
|
|
3238
|
+
handleFileUpload(
|
|
3239
|
+
e.target.files
|
|
3240
|
+
);
|
|
3241
|
+
e.target.value =
|
|
3242
|
+
null; // Reset input
|
|
3243
|
+
}
|
|
3244
|
+
}}
|
|
3245
|
+
accept="image/*"
|
|
3246
|
+
/>
|
|
3247
|
+
</div>
|
|
3248
|
+
</div>
|
|
3249
|
+
</div>
|
|
3250
|
+
)}
|
|
3001
3251
|
<div className={styles.formcontainer}>
|
|
3002
3252
|
{galleryData.length > 0 ? (
|
|
3003
|
-
<
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3253
|
+
<div
|
|
3254
|
+
className={styles.galleryContainer}
|
|
3255
|
+
>
|
|
3256
|
+
<div
|
|
3257
|
+
className={
|
|
3258
|
+
styles.galleryInstructions
|
|
3259
|
+
}
|
|
3260
|
+
>
|
|
3261
|
+
<Image
|
|
3262
|
+
strokeWidth={1.5}
|
|
3263
|
+
size={16}
|
|
3264
|
+
/>
|
|
3265
|
+
<span>
|
|
3266
|
+
Tap any image to enlarge
|
|
3267
|
+
</span>
|
|
3268
|
+
</div>
|
|
3269
|
+
<div
|
|
3270
|
+
className={
|
|
3271
|
+
styles.customGalleryGrid
|
|
3272
|
+
}
|
|
3273
|
+
>
|
|
3274
|
+
{galleryData.map(
|
|
3275
|
+
(img, index) => (
|
|
3276
|
+
<div
|
|
3277
|
+
key={`gallery-item-${index}`}
|
|
3278
|
+
className={
|
|
3279
|
+
styles.galleryItem
|
|
3280
|
+
}
|
|
3281
|
+
onClick={() => {
|
|
3282
|
+
setLightboxIndex(
|
|
3283
|
+
index
|
|
3284
|
+
);
|
|
3285
|
+
setLightboxOpen(
|
|
3286
|
+
true
|
|
3287
|
+
);
|
|
3288
|
+
}}
|
|
3289
|
+
>
|
|
3290
|
+
<img
|
|
3291
|
+
src={img.src}
|
|
3292
|
+
alt={
|
|
3293
|
+
img.caption ||
|
|
3294
|
+
`Image ${
|
|
3295
|
+
index +
|
|
3296
|
+
1
|
|
3297
|
+
}`
|
|
3298
|
+
}
|
|
3299
|
+
/>
|
|
3300
|
+
{img.caption && (
|
|
3301
|
+
<div
|
|
3302
|
+
className={
|
|
3303
|
+
styles.imageCaption
|
|
3304
|
+
}
|
|
3305
|
+
>
|
|
3306
|
+
{
|
|
3307
|
+
img.caption
|
|
3308
|
+
}
|
|
3309
|
+
</div>
|
|
3310
|
+
)}
|
|
3311
|
+
<div
|
|
3312
|
+
className={
|
|
3313
|
+
styles.galleryImageOverlay
|
|
3314
|
+
}
|
|
3315
|
+
>
|
|
3316
|
+
<span>
|
|
3317
|
+
<Image
|
|
3318
|
+
strokeWidth={
|
|
3319
|
+
1.5
|
|
3320
|
+
}
|
|
3321
|
+
size={
|
|
3322
|
+
16
|
|
3323
|
+
}
|
|
3324
|
+
style={{
|
|
3325
|
+
marginRight:
|
|
3326
|
+
'6px',
|
|
3327
|
+
}}
|
|
3328
|
+
/>
|
|
3329
|
+
Enlarge
|
|
3330
|
+
</span>
|
|
3331
|
+
</div>
|
|
3332
|
+
</div>
|
|
3333
|
+
)
|
|
3334
|
+
)}
|
|
3335
|
+
</div>
|
|
3336
|
+
</div>
|
|
3007
3337
|
) : (
|
|
3008
3338
|
<div className={styles.noDataMessage}>
|
|
3339
|
+
<Image
|
|
3340
|
+
strokeWidth={1.5}
|
|
3341
|
+
size={20}
|
|
3342
|
+
/>
|
|
3009
3343
|
No images available in the gallery
|
|
3010
3344
|
</div>
|
|
3011
3345
|
)}
|
|
@@ -3014,6 +3348,14 @@ const DataGrid = forwardRef(
|
|
|
3014
3348
|
</div>
|
|
3015
3349
|
</div>
|
|
3016
3350
|
</Popup>
|
|
3351
|
+
|
|
3352
|
+
{/* Lightbox for full-size image viewing */}
|
|
3353
|
+
<Lightbox
|
|
3354
|
+
open={lightboxOpen}
|
|
3355
|
+
close={() => setLightboxOpen(false)}
|
|
3356
|
+
index={lightboxIndex}
|
|
3357
|
+
slides={galleryData.map((img) => ({ src: img.src }))}
|
|
3358
|
+
/>
|
|
3017
3359
|
</>
|
|
3018
3360
|
);
|
|
3019
3361
|
}
|
|
@@ -101,7 +101,7 @@ function MultiSelect({
|
|
|
101
101
|
|
|
102
102
|
return (
|
|
103
103
|
<SelectComponent
|
|
104
|
-
closeMenuOnSelect={!multi}
|
|
104
|
+
closeMenuOnSelect={!multi || settings.limit === 1}
|
|
105
105
|
isClearable
|
|
106
106
|
isSearchable
|
|
107
107
|
isMulti={multi}
|
|
@@ -109,7 +109,19 @@ function MultiSelect({
|
|
|
109
109
|
components={{ SelectList }}
|
|
110
110
|
options={selectOptions}
|
|
111
111
|
onChange={(inputValue, action) => {
|
|
112
|
-
|
|
112
|
+
// Special handling for limit=1: keep only the most recent selection
|
|
113
|
+
if (
|
|
114
|
+
settings.limit === 1 &&
|
|
115
|
+
multi &&
|
|
116
|
+
Array.isArray(inputValue) &&
|
|
117
|
+
inputValue.length > 1
|
|
118
|
+
) {
|
|
119
|
+
const latestSelection = inputValue[inputValue.length - 1];
|
|
120
|
+
const newValue = latestSelection ? [latestSelection] : [];
|
|
121
|
+
onChange(newValue, action, settings.id);
|
|
122
|
+
} else {
|
|
123
|
+
onChange(inputValue, action, settings.id);
|
|
124
|
+
}
|
|
113
125
|
}}
|
|
114
126
|
className={
|
|
115
127
|
className
|
|
@@ -130,6 +142,11 @@ function MultiSelect({
|
|
|
130
142
|
value={selectValue}
|
|
131
143
|
onCreateOption={handleCreate}
|
|
132
144
|
placeholder={placeholder ? placeholder : 'Select...'}
|
|
145
|
+
isOptionDisabled={
|
|
146
|
+
settings.limit && multi && settings.limit > 1
|
|
147
|
+
? () => selectValue.length >= settings.limit
|
|
148
|
+
: undefined
|
|
149
|
+
}
|
|
133
150
|
/>
|
|
134
151
|
);
|
|
135
152
|
}
|