@availity/mui-file-selector 1.1.2 → 1.2.1
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/CHANGELOG.md +14 -0
- package/dist/index.js +262 -72
- package/dist/index.mjs +248 -52
- package/package.json +2 -2
- package/src/lib/FileSelector.stories.tsx +104 -14
- package/src/lib/UploadProgressBar.test.tsx +18 -0
- package/src/lib/UploadProgressBar.tsx +61 -41
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.2.1](https://github.com/Availity/element/compare/@availity/mui-file-selector@1.2.0...@availity/mui-file-selector@1.2.1) (2025-03-21)
|
|
6
|
+
|
|
7
|
+
### Dependency Updates
|
|
8
|
+
|
|
9
|
+
* `mui-form-utils` updated to version `1.2.0`
|
|
10
|
+
* `mui-dialog` updated to version `1.2.0`
|
|
11
|
+
* `mui-textfield` updated to version `1.2.0`
|
|
12
|
+
## [1.2.0](https://github.com/Availity/element/compare/@availity/mui-file-selector@1.1.2...@availity/mui-file-selector@1.2.0) (2025-03-13)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* **mui-file-selector:** add encrypted file support ([831383d](https://github.com/Availity/element/commit/831383d7c1470f0fbb086b40f268a60925268656))
|
|
18
|
+
|
|
5
19
|
## [1.1.2](https://github.com/Availity/element/compare/@availity/mui-file-selector@1.1.1...@availity/mui-file-selector@1.1.2) (2025-03-12)
|
|
6
20
|
|
|
7
21
|
## [1.1.1](https://github.com/Availity/element/compare/@availity/mui-file-selector@1.1.0...@availity/mui-file-selector@1.1.1) (2025-03-07)
|
package/dist/index.js
CHANGED
|
@@ -347,46 +347,236 @@ var ErrorAlert = ({ errors, fileName, id, onClose }) => {
|
|
|
347
347
|
|
|
348
348
|
// src/lib/FileList.tsx
|
|
349
349
|
var import_mui_list2 = require("@availity/mui-list");
|
|
350
|
-
var
|
|
351
|
-
var
|
|
352
|
-
var
|
|
350
|
+
var import_mui_button4 = require("@availity/mui-button");
|
|
351
|
+
var import_mui_icon5 = require("@availity/mui-icon");
|
|
352
|
+
var import_mui_layout4 = require("@availity/mui-layout");
|
|
353
353
|
var import_mui_divider2 = require("@availity/mui-divider");
|
|
354
354
|
|
|
355
355
|
// src/lib/UploadProgressBar.tsx
|
|
356
|
-
var
|
|
357
|
-
var
|
|
356
|
+
var import_react3 = require("react");
|
|
357
|
+
var import_mui_button3 = require("@availity/mui-button");
|
|
358
|
+
|
|
359
|
+
// ../dialog/src/lib/Dialog.tsx
|
|
360
|
+
var import_Dialog = __toESM(require("@mui/material/Dialog"));
|
|
361
|
+
var import_styles2 = require("@mui/material/styles");
|
|
362
|
+
var import_mui_button2 = require("@availity/mui-button");
|
|
358
363
|
var import_mui_icon2 = require("@availity/mui-icon");
|
|
359
|
-
var import_mui_list = require("@availity/mui-list");
|
|
360
364
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
365
|
+
var CloseButton = (args) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_mui_button2.IconButton, __spreadProps(__spreadValues({ title: "Close Dialog", color: "secondary" }, args), { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_mui_icon2.CloseIcon, { fontSize: "xsmall" }) }));
|
|
366
|
+
var CloseButtonSlot = (0, import_styles2.styled)(CloseButton, {
|
|
367
|
+
name: "MuiDialog",
|
|
368
|
+
slot: "AvCloseButton",
|
|
369
|
+
overridesResolver: (props, styles) => styles.avCloseButton
|
|
370
|
+
})({
|
|
371
|
+
position: "absolute",
|
|
372
|
+
top: ".5rem",
|
|
373
|
+
right: ".5rem",
|
|
374
|
+
"~ .MuiDialogTitle-root": {
|
|
375
|
+
marginRight: "3.5rem"
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
var Dialog = (_a) => {
|
|
379
|
+
var _b = _a, { children, closeButton = true, onClose } = _b, rest = __objRest(_b, ["children", "closeButton", "onClose"]);
|
|
380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_Dialog.default, __spreadProps(__spreadValues({ onClose }, rest), { children: [
|
|
381
|
+
closeButton ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseButtonSlot, { onClick: onClose }) : null,
|
|
382
|
+
children
|
|
383
|
+
] }));
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// ../dialog/src/lib/DialogActions.tsx
|
|
387
|
+
var import_DialogActions = __toESM(require("@mui/material/DialogActions"));
|
|
388
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
389
|
+
var DialogActions = (_a) => {
|
|
390
|
+
var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
|
|
391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_DialogActions.default, __spreadProps(__spreadValues({}, rest), { children }));
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// ../dialog/src/lib/DialogContent.tsx
|
|
395
|
+
var import_DialogContent = __toESM(require("@mui/material/DialogContent"));
|
|
396
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
397
|
+
var DialogContent = (_a) => {
|
|
398
|
+
var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
|
|
399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_DialogContent.default, __spreadProps(__spreadValues({}, rest), { children }));
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
// ../dialog/src/lib/DialogContentText.tsx
|
|
403
|
+
var import_DialogContentText = __toESM(require("@mui/material/DialogContentText"));
|
|
404
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
405
|
+
|
|
406
|
+
// ../dialog/src/lib/DialogTitle.tsx
|
|
407
|
+
var import_DialogTitle = __toESM(require("@mui/material/DialogTitle"));
|
|
408
|
+
var import_mui_alert2 = require("@availity/mui-alert");
|
|
409
|
+
var import_styles3 = require("@mui/material/styles");
|
|
410
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
411
|
+
var AlertIcon = (0, import_styles3.styled)("div", {
|
|
412
|
+
name: "MuiDialogTitle",
|
|
413
|
+
slot: "AvIcon",
|
|
414
|
+
overridesResolver: (props, styles) => styles.avIcon
|
|
415
|
+
})({
|
|
416
|
+
display: "inline-flex",
|
|
417
|
+
fontSize: "inherit",
|
|
418
|
+
marginRight: ".5rem",
|
|
419
|
+
verticalAlign: "text-bottom"
|
|
420
|
+
});
|
|
421
|
+
var DialogTitle = (_a) => {
|
|
422
|
+
var _b = _a, { children, component = "h2", icon, variant = "h5" } = _b, rest = __objRest(_b, ["children", "component", "icon", "variant"]);
|
|
423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_DialogTitle.default, __spreadProps(__spreadValues({ component, variant }, rest), { children: [
|
|
424
|
+
icon ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AlertIcon, { children: import_mui_alert2.AlertIcons[icon] }) : null,
|
|
425
|
+
children
|
|
426
|
+
] }));
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
// src/lib/UploadProgressBar.tsx
|
|
430
|
+
var import_mui_form_utils3 = require("@availity/mui-form-utils");
|
|
431
|
+
var import_mui_icon3 = require("@availity/mui-icon");
|
|
432
|
+
var import_mui_layout3 = require("@availity/mui-layout");
|
|
433
|
+
var import_mui_list = require("@availity/mui-list");
|
|
434
|
+
var import_mui_progress = require("@availity/mui-progress");
|
|
435
|
+
|
|
436
|
+
// ../textfield/src/lib/TextField.tsx
|
|
437
|
+
var import_react2 = require("react");
|
|
438
|
+
var import_TextField = __toESM(require("@mui/material/TextField"));
|
|
439
|
+
var import_mui_form_utils2 = require("@availity/mui-form-utils");
|
|
440
|
+
var import_mui_layout2 = require("@availity/mui-layout");
|
|
441
|
+
var import_styles4 = require("@mui/material/styles");
|
|
442
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
443
|
+
var SelectPlaceholder = (0, import_styles4.styled)("span", {
|
|
444
|
+
name: "MuiTextField",
|
|
445
|
+
slot: "SelectPlaceholder",
|
|
446
|
+
overridesResolver: (props, styles) => styles.avFilled
|
|
447
|
+
})(({ theme }) => ({ opacity: 1, color: theme.palette.grey[400] }));
|
|
448
|
+
var TextField = (0, import_react2.forwardRef)((props, ref) => {
|
|
449
|
+
var _b, _c, _d, _e, _f, _g, _h;
|
|
450
|
+
const _a = props, {
|
|
451
|
+
InputProps: InputProps2,
|
|
452
|
+
helpTopicId,
|
|
453
|
+
InputLabelProps,
|
|
454
|
+
FormHelperTextProps: FormHelperTextProps2,
|
|
455
|
+
required,
|
|
456
|
+
SelectProps: SelectProps2,
|
|
457
|
+
inputProps,
|
|
458
|
+
helperText,
|
|
459
|
+
showCharacterCount = false
|
|
460
|
+
} = _a, rest = __objRest(_a, [
|
|
461
|
+
"InputProps",
|
|
462
|
+
"helpTopicId",
|
|
463
|
+
"InputLabelProps",
|
|
464
|
+
"FormHelperTextProps",
|
|
465
|
+
"required",
|
|
466
|
+
"SelectProps",
|
|
467
|
+
"inputProps",
|
|
468
|
+
"helperText",
|
|
469
|
+
"showCharacterCount"
|
|
470
|
+
]);
|
|
471
|
+
const [openDetected, setOpenDetected] = (0, import_react2.useState)(false);
|
|
472
|
+
const [charCount, setCharCount] = (0, import_react2.useState)(0);
|
|
473
|
+
const resolvedProps = (props2) => !props2 || Object.keys(props2).length === 0 ? void 0 : props2;
|
|
474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
475
|
+
import_TextField.default,
|
|
476
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
477
|
+
onChange: (event) => {
|
|
478
|
+
setCharCount(event.target.value.length);
|
|
479
|
+
if (rest.onChange) rest.onChange(event);
|
|
480
|
+
},
|
|
481
|
+
helperText: showCharacterCount ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_mui_layout2.Grid, { container: true, justifyContent: "space-between", children: [
|
|
482
|
+
helperText,
|
|
483
|
+
" ",
|
|
484
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: { marginLeft: 4 }, children: [
|
|
485
|
+
charCount || 0,
|
|
486
|
+
"/",
|
|
487
|
+
(inputProps == null ? void 0 : inputProps.maxLength) || ((_c = (_b = rest.slotProps) == null ? void 0 : _b.htmlInput) == null ? void 0 : _c.maxLength)
|
|
488
|
+
] })
|
|
489
|
+
] }) : helperText,
|
|
490
|
+
slots: { formHelperText: import_mui_form_utils2.FormHelperText },
|
|
491
|
+
slotProps: {
|
|
492
|
+
input: resolvedProps(__spreadValues(__spreadValues(__spreadValues({}, InputProps2), import_mui_form_utils2.InputPropOverrides), (_d = rest.slotProps) == null ? void 0 : _d.input)),
|
|
493
|
+
htmlInput: resolvedProps(__spreadValues(__spreadValues({ "aria-required": required }, inputProps), (_e = rest.slotProps) == null ? void 0 : _e.htmlInput)),
|
|
494
|
+
select: resolvedProps(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
|
|
495
|
+
displayEmpty: !!rest.placeholder,
|
|
496
|
+
renderValue: (value) => rest.placeholder && (!value || Array.isArray(value) && value.length === 0) ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectPlaceholder, { className: "MuiSelect-placeholder", children: rest.placeholder }) : value
|
|
497
|
+
}, SelectProps2), import_mui_form_utils2.SelectPropOverrides), (0, import_mui_form_utils2.SelectAccessibilityOverrides)(openDetected, setOpenDetected, SelectProps2 == null ? void 0 : SelectProps2.open)), (_f = rest.slotProps) == null ? void 0 : _f.select)),
|
|
498
|
+
inputLabel: resolvedProps(__spreadValues(__spreadValues({
|
|
499
|
+
component: import_mui_form_utils2.FormLabel,
|
|
500
|
+
helpTopicId,
|
|
501
|
+
required,
|
|
502
|
+
shrink: true
|
|
503
|
+
}, InputLabelProps), (_g = rest.slotProps) == null ? void 0 : _g.inputLabel)),
|
|
504
|
+
formHelperText: resolvedProps(__spreadValues(__spreadValues({ component: "div" }, FormHelperTextProps2), (_h = rest.slotProps) == null ? void 0 : _h.formHelperText))
|
|
505
|
+
},
|
|
506
|
+
ref
|
|
507
|
+
})
|
|
508
|
+
);
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
// src/lib/UploadProgressBar.tsx
|
|
512
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
361
513
|
var UploadProgressBar = ({ upload, onProgress, onError, onSuccess }) => {
|
|
362
|
-
const [statePercentage, setStatePercentage] = (0,
|
|
363
|
-
const [
|
|
514
|
+
const [statePercentage, setStatePercentage] = (0, import_react3.useState)(upload.percentage || 0);
|
|
515
|
+
const [errorMessage, setErrorMessage] = (0, import_react3.useState)(upload.errorMessage || "");
|
|
516
|
+
const [password, setPassword] = (0, import_react3.useState)("");
|
|
517
|
+
const [showPassword, setShowPassword] = (0, import_react3.useState)(false);
|
|
518
|
+
const [modalOpen, setModalOpen] = (0, import_react3.useState)(false);
|
|
364
519
|
const handleOnProgress = () => {
|
|
365
520
|
setStatePercentage(upload.percentage);
|
|
366
|
-
|
|
521
|
+
setErrorMessage("");
|
|
367
522
|
if (onProgress) onProgress(upload);
|
|
368
523
|
};
|
|
369
524
|
const handleOnError = () => {
|
|
370
|
-
|
|
525
|
+
setErrorMessage(upload.errorMessage || "Error");
|
|
371
526
|
if (onError) onError(upload);
|
|
372
527
|
};
|
|
373
528
|
const handleOnSuccess = () => {
|
|
374
529
|
setStatePercentage(100);
|
|
375
|
-
|
|
530
|
+
setErrorMessage("");
|
|
376
531
|
if (onSuccess) onSuccess(upload);
|
|
377
532
|
};
|
|
533
|
+
const toggleModal = () => {
|
|
534
|
+
setModalOpen((prev) => !prev);
|
|
535
|
+
setPassword("");
|
|
536
|
+
};
|
|
537
|
+
const verifyPassword = (event) => {
|
|
538
|
+
event.preventDefault();
|
|
539
|
+
event.stopPropagation();
|
|
540
|
+
upload.sendPassword(password);
|
|
541
|
+
toggleModal();
|
|
542
|
+
};
|
|
543
|
+
const handlePasswordChange = (event) => {
|
|
544
|
+
setPassword(event.target.value);
|
|
545
|
+
};
|
|
378
546
|
upload.onProgress.push(handleOnProgress);
|
|
379
547
|
upload.onSuccess.push(handleOnSuccess);
|
|
380
548
|
upload.onError.push(handleOnError);
|
|
381
|
-
return
|
|
382
|
-
/* @__PURE__ */ (0,
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
549
|
+
return errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_mui_layout3.Box, { sx: { display: "flex", flexWrap: "wrap", columnGap: "4px" }, children: [
|
|
550
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_mui_list.ListItemText, { slotProps: { primary: { color: "text.error", variant: "body2", component: "div" } }, children: [
|
|
551
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_icon3.WarningTriangleIcon, { sx: { verticalAlign: "middle", mt: "-2px" } }),
|
|
552
|
+
" ",
|
|
553
|
+
errorMessage
|
|
554
|
+
] }),
|
|
555
|
+
upload.status === "encrypted" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pwRequired", children: [
|
|
556
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_button3.Button, { color: "secondary", size: "small", onClick: toggleModal, children: "Enter Password" }),
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Dialog, { open: modalOpen, onClose: toggleModal, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: verifyPassword, children: [
|
|
558
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogTitle, { children: "Enter Password" }),
|
|
559
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
560
|
+
TextField,
|
|
561
|
+
{
|
|
562
|
+
type: showPassword ? "text" : "password",
|
|
563
|
+
name: "upload-password",
|
|
564
|
+
label: "Password",
|
|
565
|
+
onChange: handlePasswordChange,
|
|
566
|
+
autoFocus: true,
|
|
567
|
+
InputProps: {
|
|
568
|
+
endAdornment: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_form_utils3.InputAdornment, { position: "end", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_button3.IconButton, { title: "password visibility", onClick: () => setShowPassword((prev) => !prev), edge: "end", children: showPassword ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_icon3.EyeIcon, { fontSize: "small" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_icon3.EyeSlashIcon, { fontSize: "small" }) }) })
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
) }),
|
|
572
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogActions, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_button3.Button, { color: "primary", type: "submit", children: "Ok" }) })
|
|
573
|
+
] }) })
|
|
574
|
+
] })
|
|
575
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_progress.LinearProgress, { value: statePercentage, "aria-label": `${upload.file.name}-progress` });
|
|
386
576
|
};
|
|
387
577
|
|
|
388
578
|
// src/lib/util.ts
|
|
389
|
-
var
|
|
579
|
+
var import_mui_icon4 = require("@availity/mui-icon");
|
|
390
580
|
function formatBytes(bytes, decimals = 2) {
|
|
391
581
|
if (!+bytes) return "0 Bytes";
|
|
392
582
|
const k = 1024;
|
|
@@ -396,30 +586,30 @@ function formatBytes(bytes, decimals = 2) {
|
|
|
396
586
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
|
|
397
587
|
}
|
|
398
588
|
var FILE_EXT_ICONS = {
|
|
399
|
-
png:
|
|
400
|
-
jpg:
|
|
401
|
-
jpeg:
|
|
402
|
-
gif:
|
|
403
|
-
csv:
|
|
404
|
-
ppt:
|
|
405
|
-
pptx:
|
|
406
|
-
xls:
|
|
407
|
-
xlsx:
|
|
408
|
-
doc:
|
|
409
|
-
docx:
|
|
410
|
-
txt:
|
|
411
|
-
text:
|
|
412
|
-
zip:
|
|
413
|
-
"7zip":
|
|
414
|
-
xml:
|
|
415
|
-
html:
|
|
416
|
-
pdf:
|
|
589
|
+
png: import_mui_icon4.FileImageIcon,
|
|
590
|
+
jpg: import_mui_icon4.FileImageIcon,
|
|
591
|
+
jpeg: import_mui_icon4.FileImageIcon,
|
|
592
|
+
gif: import_mui_icon4.FileImageIcon,
|
|
593
|
+
csv: import_mui_icon4.FileCsvIcon,
|
|
594
|
+
ppt: import_mui_icon4.FilePowerpointIcon,
|
|
595
|
+
pptx: import_mui_icon4.FilePowerpointIcon,
|
|
596
|
+
xls: import_mui_icon4.FileExcelIcon,
|
|
597
|
+
xlsx: import_mui_icon4.FileExcelIcon,
|
|
598
|
+
doc: import_mui_icon4.FileWordIcon,
|
|
599
|
+
docx: import_mui_icon4.FileWordIcon,
|
|
600
|
+
txt: import_mui_icon4.FileLinesIcon,
|
|
601
|
+
text: import_mui_icon4.FileLinesIcon,
|
|
602
|
+
zip: import_mui_icon4.FileArchiveIcon,
|
|
603
|
+
"7zip": import_mui_icon4.FileArchiveIcon,
|
|
604
|
+
xml: import_mui_icon4.FileCodeIcon,
|
|
605
|
+
html: import_mui_icon4.FileCodeIcon,
|
|
606
|
+
pdf: import_mui_icon4.FilePdfIcon
|
|
417
607
|
};
|
|
418
608
|
var isValidKey = (key) => key ? key in FILE_EXT_ICONS : false;
|
|
419
609
|
var getFileExtIcon = (fileName) => {
|
|
420
610
|
var _a;
|
|
421
611
|
const ext = ((_a = fileName.split(".").pop()) == null ? void 0 : _a.toLowerCase()) || "";
|
|
422
|
-
const icon = isValidKey(ext) ? FILE_EXT_ICONS[ext] :
|
|
612
|
+
const icon = isValidKey(ext) ? FILE_EXT_ICONS[ext] : import_mui_icon4.FileIcon;
|
|
423
613
|
return icon;
|
|
424
614
|
};
|
|
425
615
|
|
|
@@ -449,7 +639,7 @@ function useUploadCore(file, options, queryOptions) {
|
|
|
449
639
|
}
|
|
450
640
|
|
|
451
641
|
// src/lib/FileList.tsx
|
|
452
|
-
var
|
|
642
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
453
643
|
var FileRow = ({
|
|
454
644
|
file,
|
|
455
645
|
options,
|
|
@@ -460,31 +650,31 @@ var FileRow = ({
|
|
|
460
650
|
}) => {
|
|
461
651
|
const Icon = getFileExtIcon(file.name);
|
|
462
652
|
const { data: upload } = useUploadCore(file, options, queryOptions);
|
|
463
|
-
if (CustomRow) return /* @__PURE__ */ (0,
|
|
653
|
+
if (CustomRow) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CustomRow, { upload, options, onRemoveFile });
|
|
464
654
|
if (!upload) return null;
|
|
465
|
-
return /* @__PURE__ */ (0,
|
|
655
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
466
656
|
import_mui_list2.ListItem,
|
|
467
657
|
{
|
|
468
658
|
disableGutters: true,
|
|
469
|
-
secondaryAction: !disableRemove && /* @__PURE__ */ (0,
|
|
470
|
-
|
|
659
|
+
secondaryAction: !disableRemove && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
660
|
+
import_mui_button4.IconButton,
|
|
471
661
|
{
|
|
472
662
|
title: "remove file",
|
|
473
663
|
edge: "end",
|
|
474
664
|
onClick: () => {
|
|
475
665
|
onRemoveFile(upload.id, upload);
|
|
476
666
|
},
|
|
477
|
-
children: /* @__PURE__ */ (0,
|
|
667
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_icon5.DeleteIcon, {})
|
|
478
668
|
}
|
|
479
669
|
),
|
|
480
670
|
children: [
|
|
481
|
-
/* @__PURE__ */ (0,
|
|
482
|
-
/* @__PURE__ */ (0,
|
|
483
|
-
/* @__PURE__ */ (0,
|
|
484
|
-
/* @__PURE__ */ (0,
|
|
485
|
-
/* @__PURE__ */ (0,
|
|
671
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_mui_layout4.Grid, { container: true, spacing: 2, alignItems: "center", justifyContent: "space-between", width: "100%", children: [
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout4.Grid, { size: { xs: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.ListItemIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Icon, {}) }) }),
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout4.Grid, { size: { xs: 3 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.ListItemText, { children: upload.trimFileName(upload.file.name) }) }),
|
|
674
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout4.Grid, { size: { xs: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.ListItemText, { children: formatBytes(upload.file.size) }) }),
|
|
675
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout4.Grid, { size: { xs: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(UploadProgressBar, { upload }) })
|
|
486
676
|
] }),
|
|
487
|
-
/* @__PURE__ */ (0,
|
|
677
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_divider2.Divider, {})
|
|
488
678
|
]
|
|
489
679
|
}
|
|
490
680
|
);
|
|
@@ -498,8 +688,8 @@ var FileList = ({
|
|
|
498
688
|
disableRemove
|
|
499
689
|
}) => {
|
|
500
690
|
if (files.length === 0) return null;
|
|
501
|
-
return /* @__PURE__ */ (0,
|
|
502
|
-
return /* @__PURE__ */ (0,
|
|
691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.List, { children: files.map((file) => {
|
|
692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
503
693
|
FileRow,
|
|
504
694
|
{
|
|
505
695
|
file,
|
|
@@ -515,15 +705,15 @@ var FileList = ({
|
|
|
515
705
|
};
|
|
516
706
|
|
|
517
707
|
// src/lib/FileSelector.tsx
|
|
518
|
-
var
|
|
708
|
+
var import_react4 = require("react");
|
|
519
709
|
var import_react_hook_form3 = require("react-hook-form");
|
|
520
710
|
var import_react_query2 = require("@tanstack/react-query");
|
|
521
|
-
var
|
|
711
|
+
var import_mui_layout5 = require("@availity/mui-layout");
|
|
522
712
|
var import_mui_typography4 = require("@availity/mui-typography");
|
|
523
713
|
|
|
524
714
|
// src/lib/FileTypesMessage.tsx
|
|
525
715
|
var import_mui_typography2 = require("@availity/mui-typography");
|
|
526
|
-
var
|
|
716
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
527
717
|
var FileTypesMessage = ({
|
|
528
718
|
allowedFileTypes = [],
|
|
529
719
|
maxFileSize,
|
|
@@ -531,7 +721,7 @@ var FileTypesMessage = ({
|
|
|
531
721
|
}) => {
|
|
532
722
|
const fileSizeMsg = typeof maxFileSize === "number" ? `Maximum file size is ${formatBytes(maxFileSize)}. ` : null;
|
|
533
723
|
const fileTypesMsg = allowedFileTypes.length > 0 ? `Supported file types include: ${allowedFileTypes.join(", ")}` : "All file types allowed.";
|
|
534
|
-
return /* @__PURE__ */ (0,
|
|
724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_mui_typography2.Typography, { variant, children: [
|
|
535
725
|
fileSizeMsg,
|
|
536
726
|
fileTypesMsg
|
|
537
727
|
] });
|
|
@@ -539,9 +729,9 @@ var FileTypesMessage = ({
|
|
|
539
729
|
|
|
540
730
|
// src/lib/HeaderMessage.tsx
|
|
541
731
|
var import_mui_typography3 = require("@availity/mui-typography");
|
|
542
|
-
var
|
|
732
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
543
733
|
var HeaderMessage = ({ maxFiles, maxSize }) => {
|
|
544
|
-
return /* @__PURE__ */ (0,
|
|
734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_mui_typography3.Typography, { variant: "h6", children: [
|
|
545
735
|
"Attach up to ",
|
|
546
736
|
maxFiles,
|
|
547
737
|
" file(s), with a maximum individual size of ",
|
|
@@ -550,7 +740,7 @@ var HeaderMessage = ({ maxFiles, maxSize }) => {
|
|
|
550
740
|
};
|
|
551
741
|
|
|
552
742
|
// src/lib/FileSelector.tsx
|
|
553
|
-
var
|
|
743
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
554
744
|
var CLOUD_URL = "/cloud/web/appl/vault/upload/v1/resumable";
|
|
555
745
|
var FileSelector = ({
|
|
556
746
|
name,
|
|
@@ -577,8 +767,8 @@ var FileSelector = ({
|
|
|
577
767
|
validator,
|
|
578
768
|
disableRemove
|
|
579
769
|
}) => {
|
|
580
|
-
const [totalSize, setTotalSize] = (0,
|
|
581
|
-
const [fileRejections, setFileRejections] = (0,
|
|
770
|
+
const [totalSize, setTotalSize] = (0, import_react4.useState)(0);
|
|
771
|
+
const [fileRejections, setFileRejections] = (0, import_react4.useState)([]);
|
|
582
772
|
const client = (0, import_react_query2.useQueryClient)();
|
|
583
773
|
const formMethods = (0, import_react_hook_form3.useFormContext)();
|
|
584
774
|
const options = __spreadProps(__spreadValues({}, uploadOptions), {
|
|
@@ -612,10 +802,10 @@ var FileSelector = ({
|
|
|
612
802
|
const rejections = fileRejections.filter((value) => value.id !== id);
|
|
613
803
|
setFileRejections(rejections);
|
|
614
804
|
};
|
|
615
|
-
return /* @__PURE__ */ (0,
|
|
616
|
-
enableDropArea ? /* @__PURE__ */ (0,
|
|
617
|
-
label ? /* @__PURE__ */ (0,
|
|
618
|
-
/* @__PURE__ */ (0,
|
|
805
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
806
|
+
enableDropArea ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
807
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_mui_typography4.Typography, { marginBottom: "4px", children: label }) : null,
|
|
808
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
619
809
|
Dropzone,
|
|
620
810
|
{
|
|
621
811
|
name,
|
|
@@ -632,15 +822,15 @@ var FileSelector = ({
|
|
|
632
822
|
validator
|
|
633
823
|
}
|
|
634
824
|
),
|
|
635
|
-
/* @__PURE__ */ (0,
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FileTypesMessage, { allowedFileTypes, maxFileSize: maxSize, variant: "caption" }),
|
|
636
826
|
children
|
|
637
|
-
] }) : /* @__PURE__ */ (0,
|
|
638
|
-
/* @__PURE__ */ (0,
|
|
639
|
-
/* @__PURE__ */ (0,
|
|
640
|
-
/* @__PURE__ */ (0,
|
|
827
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_mui_layout5.Grid, { container: true, rowSpacing: 3, flexDirection: "column", children: [
|
|
828
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_mui_layout5.Grid, { children: [
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(HeaderMessage, { maxFiles, maxSize }),
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FileTypesMessage, { allowedFileTypes, variant: "body2" })
|
|
641
831
|
] }),
|
|
642
|
-
children ? /* @__PURE__ */ (0,
|
|
643
|
-
/* @__PURE__ */ (0,
|
|
832
|
+
children ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_mui_layout5.Grid, { children }) : null,
|
|
833
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_mui_layout5.Grid, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
644
834
|
Dropzone,
|
|
645
835
|
{
|
|
646
836
|
name,
|
|
@@ -658,7 +848,7 @@ var FileSelector = ({
|
|
|
658
848
|
}
|
|
659
849
|
) })
|
|
660
850
|
] }),
|
|
661
|
-
fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */ (0,
|
|
851
|
+
fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
662
852
|
ErrorAlert,
|
|
663
853
|
{
|
|
664
854
|
errors: rejection.errors,
|
|
@@ -668,7 +858,7 @@ var FileSelector = ({
|
|
|
668
858
|
},
|
|
669
859
|
rejection.id
|
|
670
860
|
)) : null,
|
|
671
|
-
/* @__PURE__ */ (0,
|
|
861
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
672
862
|
FileList,
|
|
673
863
|
{
|
|
674
864
|
files: files || [],
|
package/dist/index.mjs
CHANGED
|
@@ -305,42 +305,238 @@ var ErrorAlert = ({ errors, fileName, id, onClose }) => {
|
|
|
305
305
|
|
|
306
306
|
// src/lib/FileList.tsx
|
|
307
307
|
import { List, ListItem, ListItemText as ListItemText2, ListItemIcon } from "@availity/mui-list";
|
|
308
|
-
import { IconButton } from "@availity/mui-button";
|
|
308
|
+
import { IconButton as IconButton3 } from "@availity/mui-button";
|
|
309
309
|
import { DeleteIcon } from "@availity/mui-icon";
|
|
310
|
-
import { Grid } from "@availity/mui-layout";
|
|
310
|
+
import { Grid as Grid2 } from "@availity/mui-layout";
|
|
311
311
|
import { Divider as Divider2 } from "@availity/mui-divider";
|
|
312
312
|
|
|
313
313
|
// src/lib/UploadProgressBar.tsx
|
|
314
|
-
import { useState } from "react";
|
|
315
|
-
import {
|
|
316
|
-
|
|
314
|
+
import { useState as useState2 } from "react";
|
|
315
|
+
import { Button as Button2, IconButton as IconButton2 } from "@availity/mui-button";
|
|
316
|
+
|
|
317
|
+
// ../dialog/src/lib/Dialog.tsx
|
|
318
|
+
import MuiDialog from "@mui/material/Dialog";
|
|
319
|
+
import { styled as styled2 } from "@mui/material/styles";
|
|
320
|
+
import { IconButton } from "@availity/mui-button";
|
|
321
|
+
import { CloseIcon } from "@availity/mui-icon";
|
|
322
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
323
|
+
var CloseButton = (args) => /* @__PURE__ */ jsx4(IconButton, __spreadProps(__spreadValues({ title: "Close Dialog", color: "secondary" }, args), { children: /* @__PURE__ */ jsx4(CloseIcon, { fontSize: "xsmall" }) }));
|
|
324
|
+
var CloseButtonSlot = styled2(CloseButton, {
|
|
325
|
+
name: "MuiDialog",
|
|
326
|
+
slot: "AvCloseButton",
|
|
327
|
+
overridesResolver: (props, styles) => styles.avCloseButton
|
|
328
|
+
})({
|
|
329
|
+
position: "absolute",
|
|
330
|
+
top: ".5rem",
|
|
331
|
+
right: ".5rem",
|
|
332
|
+
"~ .MuiDialogTitle-root": {
|
|
333
|
+
marginRight: "3.5rem"
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
var Dialog = (_a) => {
|
|
337
|
+
var _b = _a, { children, closeButton = true, onClose } = _b, rest = __objRest(_b, ["children", "closeButton", "onClose"]);
|
|
338
|
+
return /* @__PURE__ */ jsxs4(MuiDialog, __spreadProps(__spreadValues({ onClose }, rest), { children: [
|
|
339
|
+
closeButton ? /* @__PURE__ */ jsx4(CloseButtonSlot, { onClick: onClose }) : null,
|
|
340
|
+
children
|
|
341
|
+
] }));
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
// ../dialog/src/lib/DialogActions.tsx
|
|
345
|
+
import MuiDialogActions from "@mui/material/DialogActions";
|
|
346
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
347
|
+
var DialogActions = (_a) => {
|
|
348
|
+
var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
|
|
349
|
+
return /* @__PURE__ */ jsx5(MuiDialogActions, __spreadProps(__spreadValues({}, rest), { children }));
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
// ../dialog/src/lib/DialogContent.tsx
|
|
353
|
+
import MuiDialogContent from "@mui/material/DialogContent";
|
|
354
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
355
|
+
var DialogContent = (_a) => {
|
|
356
|
+
var _b = _a, { children } = _b, rest = __objRest(_b, ["children"]);
|
|
357
|
+
return /* @__PURE__ */ jsx6(MuiDialogContent, __spreadProps(__spreadValues({}, rest), { children }));
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
// ../dialog/src/lib/DialogContentText.tsx
|
|
361
|
+
import MuiDialogContentText from "@mui/material/DialogContentText";
|
|
362
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
363
|
+
|
|
364
|
+
// ../dialog/src/lib/DialogTitle.tsx
|
|
365
|
+
import MuiDialogTitle from "@mui/material/DialogTitle";
|
|
366
|
+
import { AlertIcons } from "@availity/mui-alert";
|
|
367
|
+
import { styled as styled3 } from "@mui/material/styles";
|
|
368
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
369
|
+
var AlertIcon = styled3("div", {
|
|
370
|
+
name: "MuiDialogTitle",
|
|
371
|
+
slot: "AvIcon",
|
|
372
|
+
overridesResolver: (props, styles) => styles.avIcon
|
|
373
|
+
})({
|
|
374
|
+
display: "inline-flex",
|
|
375
|
+
fontSize: "inherit",
|
|
376
|
+
marginRight: ".5rem",
|
|
377
|
+
verticalAlign: "text-bottom"
|
|
378
|
+
});
|
|
379
|
+
var DialogTitle = (_a) => {
|
|
380
|
+
var _b = _a, { children, component = "h2", icon, variant = "h5" } = _b, rest = __objRest(_b, ["children", "component", "icon", "variant"]);
|
|
381
|
+
return /* @__PURE__ */ jsxs5(MuiDialogTitle, __spreadProps(__spreadValues({ component, variant }, rest), { children: [
|
|
382
|
+
icon ? /* @__PURE__ */ jsx8(AlertIcon, { children: AlertIcons[icon] }) : null,
|
|
383
|
+
children
|
|
384
|
+
] }));
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// src/lib/UploadProgressBar.tsx
|
|
388
|
+
import { InputAdornment } from "@availity/mui-form-utils";
|
|
389
|
+
import { EyeIcon, EyeSlashIcon, WarningTriangleIcon } from "@availity/mui-icon";
|
|
390
|
+
import { Box as Box2 } from "@availity/mui-layout";
|
|
317
391
|
import { ListItemText } from "@availity/mui-list";
|
|
318
|
-
import {
|
|
392
|
+
import { LinearProgress } from "@availity/mui-progress";
|
|
393
|
+
|
|
394
|
+
// ../textfield/src/lib/TextField.tsx
|
|
395
|
+
import { forwardRef, useState } from "react";
|
|
396
|
+
import MuiTextField from "@mui/material/TextField";
|
|
397
|
+
import {
|
|
398
|
+
FormHelperText,
|
|
399
|
+
FormLabel,
|
|
400
|
+
InputPropOverrides,
|
|
401
|
+
SelectAccessibilityOverrides,
|
|
402
|
+
SelectPropOverrides
|
|
403
|
+
} from "@availity/mui-form-utils";
|
|
404
|
+
import { Grid } from "@availity/mui-layout";
|
|
405
|
+
import { styled as styled4 } from "@mui/material/styles";
|
|
406
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
407
|
+
var SelectPlaceholder = styled4("span", {
|
|
408
|
+
name: "MuiTextField",
|
|
409
|
+
slot: "SelectPlaceholder",
|
|
410
|
+
overridesResolver: (props, styles) => styles.avFilled
|
|
411
|
+
})(({ theme }) => ({ opacity: 1, color: theme.palette.grey[400] }));
|
|
412
|
+
var TextField = forwardRef((props, ref) => {
|
|
413
|
+
var _b, _c, _d, _e, _f, _g, _h;
|
|
414
|
+
const _a = props, {
|
|
415
|
+
InputProps: InputProps2,
|
|
416
|
+
helpTopicId,
|
|
417
|
+
InputLabelProps,
|
|
418
|
+
FormHelperTextProps: FormHelperTextProps2,
|
|
419
|
+
required,
|
|
420
|
+
SelectProps: SelectProps2,
|
|
421
|
+
inputProps,
|
|
422
|
+
helperText,
|
|
423
|
+
showCharacterCount = false
|
|
424
|
+
} = _a, rest = __objRest(_a, [
|
|
425
|
+
"InputProps",
|
|
426
|
+
"helpTopicId",
|
|
427
|
+
"InputLabelProps",
|
|
428
|
+
"FormHelperTextProps",
|
|
429
|
+
"required",
|
|
430
|
+
"SelectProps",
|
|
431
|
+
"inputProps",
|
|
432
|
+
"helperText",
|
|
433
|
+
"showCharacterCount"
|
|
434
|
+
]);
|
|
435
|
+
const [openDetected, setOpenDetected] = useState(false);
|
|
436
|
+
const [charCount, setCharCount] = useState(0);
|
|
437
|
+
const resolvedProps = (props2) => !props2 || Object.keys(props2).length === 0 ? void 0 : props2;
|
|
438
|
+
return /* @__PURE__ */ jsx9(
|
|
439
|
+
MuiTextField,
|
|
440
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
441
|
+
onChange: (event) => {
|
|
442
|
+
setCharCount(event.target.value.length);
|
|
443
|
+
if (rest.onChange) rest.onChange(event);
|
|
444
|
+
},
|
|
445
|
+
helperText: showCharacterCount ? /* @__PURE__ */ jsxs6(Grid, { container: true, justifyContent: "space-between", children: [
|
|
446
|
+
helperText,
|
|
447
|
+
" ",
|
|
448
|
+
/* @__PURE__ */ jsxs6("span", { style: { marginLeft: 4 }, children: [
|
|
449
|
+
charCount || 0,
|
|
450
|
+
"/",
|
|
451
|
+
(inputProps == null ? void 0 : inputProps.maxLength) || ((_c = (_b = rest.slotProps) == null ? void 0 : _b.htmlInput) == null ? void 0 : _c.maxLength)
|
|
452
|
+
] })
|
|
453
|
+
] }) : helperText,
|
|
454
|
+
slots: { formHelperText: FormHelperText },
|
|
455
|
+
slotProps: {
|
|
456
|
+
input: resolvedProps(__spreadValues(__spreadValues(__spreadValues({}, InputProps2), InputPropOverrides), (_d = rest.slotProps) == null ? void 0 : _d.input)),
|
|
457
|
+
htmlInput: resolvedProps(__spreadValues(__spreadValues({ "aria-required": required }, inputProps), (_e = rest.slotProps) == null ? void 0 : _e.htmlInput)),
|
|
458
|
+
select: resolvedProps(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
|
|
459
|
+
displayEmpty: !!rest.placeholder,
|
|
460
|
+
renderValue: (value) => rest.placeholder && (!value || Array.isArray(value) && value.length === 0) ? /* @__PURE__ */ jsx9(SelectPlaceholder, { className: "MuiSelect-placeholder", children: rest.placeholder }) : value
|
|
461
|
+
}, SelectProps2), SelectPropOverrides), SelectAccessibilityOverrides(openDetected, setOpenDetected, SelectProps2 == null ? void 0 : SelectProps2.open)), (_f = rest.slotProps) == null ? void 0 : _f.select)),
|
|
462
|
+
inputLabel: resolvedProps(__spreadValues(__spreadValues({
|
|
463
|
+
component: FormLabel,
|
|
464
|
+
helpTopicId,
|
|
465
|
+
required,
|
|
466
|
+
shrink: true
|
|
467
|
+
}, InputLabelProps), (_g = rest.slotProps) == null ? void 0 : _g.inputLabel)),
|
|
468
|
+
formHelperText: resolvedProps(__spreadValues(__spreadValues({ component: "div" }, FormHelperTextProps2), (_h = rest.slotProps) == null ? void 0 : _h.formHelperText))
|
|
469
|
+
},
|
|
470
|
+
ref
|
|
471
|
+
})
|
|
472
|
+
);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// src/lib/UploadProgressBar.tsx
|
|
476
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
319
477
|
var UploadProgressBar = ({ upload, onProgress, onError, onSuccess }) => {
|
|
320
|
-
const [statePercentage, setStatePercentage] =
|
|
321
|
-
const [
|
|
478
|
+
const [statePercentage, setStatePercentage] = useState2(upload.percentage || 0);
|
|
479
|
+
const [errorMessage, setErrorMessage] = useState2(upload.errorMessage || "");
|
|
480
|
+
const [password, setPassword] = useState2("");
|
|
481
|
+
const [showPassword, setShowPassword] = useState2(false);
|
|
482
|
+
const [modalOpen, setModalOpen] = useState2(false);
|
|
322
483
|
const handleOnProgress = () => {
|
|
323
484
|
setStatePercentage(upload.percentage);
|
|
324
|
-
|
|
485
|
+
setErrorMessage("");
|
|
325
486
|
if (onProgress) onProgress(upload);
|
|
326
487
|
};
|
|
327
488
|
const handleOnError = () => {
|
|
328
|
-
|
|
489
|
+
setErrorMessage(upload.errorMessage || "Error");
|
|
329
490
|
if (onError) onError(upload);
|
|
330
491
|
};
|
|
331
492
|
const handleOnSuccess = () => {
|
|
332
493
|
setStatePercentage(100);
|
|
333
|
-
|
|
494
|
+
setErrorMessage("");
|
|
334
495
|
if (onSuccess) onSuccess(upload);
|
|
335
496
|
};
|
|
497
|
+
const toggleModal = () => {
|
|
498
|
+
setModalOpen((prev) => !prev);
|
|
499
|
+
setPassword("");
|
|
500
|
+
};
|
|
501
|
+
const verifyPassword = (event) => {
|
|
502
|
+
event.preventDefault();
|
|
503
|
+
event.stopPropagation();
|
|
504
|
+
upload.sendPassword(password);
|
|
505
|
+
toggleModal();
|
|
506
|
+
};
|
|
507
|
+
const handlePasswordChange = (event) => {
|
|
508
|
+
setPassword(event.target.value);
|
|
509
|
+
};
|
|
336
510
|
upload.onProgress.push(handleOnProgress);
|
|
337
511
|
upload.onSuccess.push(handleOnSuccess);
|
|
338
512
|
upload.onError.push(handleOnError);
|
|
339
|
-
return
|
|
340
|
-
/* @__PURE__ */
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
513
|
+
return errorMessage ? /* @__PURE__ */ jsxs7(Box2, { sx: { display: "flex", flexWrap: "wrap", columnGap: "4px" }, children: [
|
|
514
|
+
/* @__PURE__ */ jsxs7(ListItemText, { slotProps: { primary: { color: "text.error", variant: "body2", component: "div" } }, children: [
|
|
515
|
+
/* @__PURE__ */ jsx10(WarningTriangleIcon, { sx: { verticalAlign: "middle", mt: "-2px" } }),
|
|
516
|
+
" ",
|
|
517
|
+
errorMessage
|
|
518
|
+
] }),
|
|
519
|
+
upload.status === "encrypted" && /* @__PURE__ */ jsxs7("div", { className: "pwRequired", children: [
|
|
520
|
+
/* @__PURE__ */ jsx10(Button2, { color: "secondary", size: "small", onClick: toggleModal, children: "Enter Password" }),
|
|
521
|
+
/* @__PURE__ */ jsx10(Dialog, { open: modalOpen, onClose: toggleModal, children: /* @__PURE__ */ jsxs7("form", { onSubmit: verifyPassword, children: [
|
|
522
|
+
/* @__PURE__ */ jsx10(DialogTitle, { children: "Enter Password" }),
|
|
523
|
+
/* @__PURE__ */ jsx10(DialogContent, { children: /* @__PURE__ */ jsx10(
|
|
524
|
+
TextField,
|
|
525
|
+
{
|
|
526
|
+
type: showPassword ? "text" : "password",
|
|
527
|
+
name: "upload-password",
|
|
528
|
+
label: "Password",
|
|
529
|
+
onChange: handlePasswordChange,
|
|
530
|
+
autoFocus: true,
|
|
531
|
+
InputProps: {
|
|
532
|
+
endAdornment: /* @__PURE__ */ jsx10(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx10(IconButton2, { title: "password visibility", onClick: () => setShowPassword((prev) => !prev), edge: "end", children: showPassword ? /* @__PURE__ */ jsx10(EyeIcon, { fontSize: "small" }) : /* @__PURE__ */ jsx10(EyeSlashIcon, { fontSize: "small" }) }) })
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
) }),
|
|
536
|
+
/* @__PURE__ */ jsx10(DialogActions, { children: /* @__PURE__ */ jsx10(Button2, { color: "primary", type: "submit", children: "Ok" }) })
|
|
537
|
+
] }) })
|
|
538
|
+
] })
|
|
539
|
+
] }) : /* @__PURE__ */ jsx10(LinearProgress, { value: statePercentage, "aria-label": `${upload.file.name}-progress` });
|
|
344
540
|
};
|
|
345
541
|
|
|
346
542
|
// src/lib/util.ts
|
|
@@ -418,7 +614,7 @@ function useUploadCore(file, options, queryOptions) {
|
|
|
418
614
|
}
|
|
419
615
|
|
|
420
616
|
// src/lib/FileList.tsx
|
|
421
|
-
import { jsx as
|
|
617
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
422
618
|
var FileRow = ({
|
|
423
619
|
file,
|
|
424
620
|
options,
|
|
@@ -429,31 +625,31 @@ var FileRow = ({
|
|
|
429
625
|
}) => {
|
|
430
626
|
const Icon = getFileExtIcon(file.name);
|
|
431
627
|
const { data: upload } = useUploadCore(file, options, queryOptions);
|
|
432
|
-
if (CustomRow) return /* @__PURE__ */
|
|
628
|
+
if (CustomRow) return /* @__PURE__ */ jsx11(CustomRow, { upload, options, onRemoveFile });
|
|
433
629
|
if (!upload) return null;
|
|
434
|
-
return /* @__PURE__ */
|
|
630
|
+
return /* @__PURE__ */ jsxs8(
|
|
435
631
|
ListItem,
|
|
436
632
|
{
|
|
437
633
|
disableGutters: true,
|
|
438
|
-
secondaryAction: !disableRemove && /* @__PURE__ */
|
|
439
|
-
|
|
634
|
+
secondaryAction: !disableRemove && /* @__PURE__ */ jsx11(
|
|
635
|
+
IconButton3,
|
|
440
636
|
{
|
|
441
637
|
title: "remove file",
|
|
442
638
|
edge: "end",
|
|
443
639
|
onClick: () => {
|
|
444
640
|
onRemoveFile(upload.id, upload);
|
|
445
641
|
},
|
|
446
|
-
children: /* @__PURE__ */
|
|
642
|
+
children: /* @__PURE__ */ jsx11(DeleteIcon, {})
|
|
447
643
|
}
|
|
448
644
|
),
|
|
449
645
|
children: [
|
|
450
|
-
/* @__PURE__ */
|
|
451
|
-
/* @__PURE__ */
|
|
452
|
-
/* @__PURE__ */
|
|
453
|
-
/* @__PURE__ */
|
|
454
|
-
/* @__PURE__ */
|
|
646
|
+
/* @__PURE__ */ jsxs8(Grid2, { container: true, spacing: 2, alignItems: "center", justifyContent: "space-between", width: "100%", children: [
|
|
647
|
+
/* @__PURE__ */ jsx11(Grid2, { size: { xs: 1 }, children: /* @__PURE__ */ jsx11(ListItemIcon, { children: /* @__PURE__ */ jsx11(Icon, {}) }) }),
|
|
648
|
+
/* @__PURE__ */ jsx11(Grid2, { size: { xs: 3 }, children: /* @__PURE__ */ jsx11(ListItemText2, { children: upload.trimFileName(upload.file.name) }) }),
|
|
649
|
+
/* @__PURE__ */ jsx11(Grid2, { size: { xs: 2 }, children: /* @__PURE__ */ jsx11(ListItemText2, { children: formatBytes(upload.file.size) }) }),
|
|
650
|
+
/* @__PURE__ */ jsx11(Grid2, { size: { xs: 6 }, children: /* @__PURE__ */ jsx11(UploadProgressBar, { upload }) })
|
|
455
651
|
] }),
|
|
456
|
-
/* @__PURE__ */
|
|
652
|
+
/* @__PURE__ */ jsx11(Divider2, {})
|
|
457
653
|
]
|
|
458
654
|
}
|
|
459
655
|
);
|
|
@@ -467,8 +663,8 @@ var FileList = ({
|
|
|
467
663
|
disableRemove
|
|
468
664
|
}) => {
|
|
469
665
|
if (files.length === 0) return null;
|
|
470
|
-
return /* @__PURE__ */
|
|
471
|
-
return /* @__PURE__ */
|
|
666
|
+
return /* @__PURE__ */ jsx11(List, { children: files.map((file) => {
|
|
667
|
+
return /* @__PURE__ */ jsx11(
|
|
472
668
|
FileRow,
|
|
473
669
|
{
|
|
474
670
|
file,
|
|
@@ -484,15 +680,15 @@ var FileList = ({
|
|
|
484
680
|
};
|
|
485
681
|
|
|
486
682
|
// src/lib/FileSelector.tsx
|
|
487
|
-
import { useState as
|
|
683
|
+
import { useState as useState3 } from "react";
|
|
488
684
|
import { useFormContext as useFormContext2 } from "react-hook-form";
|
|
489
685
|
import { useQueryClient } from "@tanstack/react-query";
|
|
490
|
-
import { Grid as
|
|
686
|
+
import { Grid as Grid3 } from "@availity/mui-layout";
|
|
491
687
|
import { Typography as Typography4 } from "@availity/mui-typography";
|
|
492
688
|
|
|
493
689
|
// src/lib/FileTypesMessage.tsx
|
|
494
690
|
import { Typography as Typography2 } from "@availity/mui-typography";
|
|
495
|
-
import { jsxs as
|
|
691
|
+
import { jsxs as jsxs9 } from "react/jsx-runtime";
|
|
496
692
|
var FileTypesMessage = ({
|
|
497
693
|
allowedFileTypes = [],
|
|
498
694
|
maxFileSize,
|
|
@@ -500,7 +696,7 @@ var FileTypesMessage = ({
|
|
|
500
696
|
}) => {
|
|
501
697
|
const fileSizeMsg = typeof maxFileSize === "number" ? `Maximum file size is ${formatBytes(maxFileSize)}. ` : null;
|
|
502
698
|
const fileTypesMsg = allowedFileTypes.length > 0 ? `Supported file types include: ${allowedFileTypes.join(", ")}` : "All file types allowed.";
|
|
503
|
-
return /* @__PURE__ */
|
|
699
|
+
return /* @__PURE__ */ jsxs9(Typography2, { variant, children: [
|
|
504
700
|
fileSizeMsg,
|
|
505
701
|
fileTypesMsg
|
|
506
702
|
] });
|
|
@@ -508,9 +704,9 @@ var FileTypesMessage = ({
|
|
|
508
704
|
|
|
509
705
|
// src/lib/HeaderMessage.tsx
|
|
510
706
|
import { Typography as Typography3 } from "@availity/mui-typography";
|
|
511
|
-
import { jsxs as
|
|
707
|
+
import { jsxs as jsxs10 } from "react/jsx-runtime";
|
|
512
708
|
var HeaderMessage = ({ maxFiles, maxSize }) => {
|
|
513
|
-
return /* @__PURE__ */
|
|
709
|
+
return /* @__PURE__ */ jsxs10(Typography3, { variant: "h6", children: [
|
|
514
710
|
"Attach up to ",
|
|
515
711
|
maxFiles,
|
|
516
712
|
" file(s), with a maximum individual size of ",
|
|
@@ -519,7 +715,7 @@ var HeaderMessage = ({ maxFiles, maxSize }) => {
|
|
|
519
715
|
};
|
|
520
716
|
|
|
521
717
|
// src/lib/FileSelector.tsx
|
|
522
|
-
import { Fragment as
|
|
718
|
+
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
523
719
|
var CLOUD_URL = "/cloud/web/appl/vault/upload/v1/resumable";
|
|
524
720
|
var FileSelector = ({
|
|
525
721
|
name,
|
|
@@ -546,8 +742,8 @@ var FileSelector = ({
|
|
|
546
742
|
validator,
|
|
547
743
|
disableRemove
|
|
548
744
|
}) => {
|
|
549
|
-
const [totalSize, setTotalSize] =
|
|
550
|
-
const [fileRejections, setFileRejections] =
|
|
745
|
+
const [totalSize, setTotalSize] = useState3(0);
|
|
746
|
+
const [fileRejections, setFileRejections] = useState3([]);
|
|
551
747
|
const client = useQueryClient();
|
|
552
748
|
const formMethods = useFormContext2();
|
|
553
749
|
const options = __spreadProps(__spreadValues({}, uploadOptions), {
|
|
@@ -581,10 +777,10 @@ var FileSelector = ({
|
|
|
581
777
|
const rejections = fileRejections.filter((value) => value.id !== id);
|
|
582
778
|
setFileRejections(rejections);
|
|
583
779
|
};
|
|
584
|
-
return /* @__PURE__ */
|
|
585
|
-
enableDropArea ? /* @__PURE__ */
|
|
586
|
-
label ? /* @__PURE__ */
|
|
587
|
-
/* @__PURE__ */
|
|
780
|
+
return /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
781
|
+
enableDropArea ? /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
782
|
+
label ? /* @__PURE__ */ jsx12(Typography4, { marginBottom: "4px", children: label }) : null,
|
|
783
|
+
/* @__PURE__ */ jsx12(
|
|
588
784
|
Dropzone,
|
|
589
785
|
{
|
|
590
786
|
name,
|
|
@@ -601,15 +797,15 @@ var FileSelector = ({
|
|
|
601
797
|
validator
|
|
602
798
|
}
|
|
603
799
|
),
|
|
604
|
-
/* @__PURE__ */
|
|
800
|
+
/* @__PURE__ */ jsx12(FileTypesMessage, { allowedFileTypes, maxFileSize: maxSize, variant: "caption" }),
|
|
605
801
|
children
|
|
606
|
-
] }) : /* @__PURE__ */
|
|
607
|
-
/* @__PURE__ */
|
|
608
|
-
/* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
802
|
+
] }) : /* @__PURE__ */ jsxs11(Grid3, { container: true, rowSpacing: 3, flexDirection: "column", children: [
|
|
803
|
+
/* @__PURE__ */ jsxs11(Grid3, { children: [
|
|
804
|
+
/* @__PURE__ */ jsx12(HeaderMessage, { maxFiles, maxSize }),
|
|
805
|
+
/* @__PURE__ */ jsx12(FileTypesMessage, { allowedFileTypes, variant: "body2" })
|
|
610
806
|
] }),
|
|
611
|
-
children ? /* @__PURE__ */
|
|
612
|
-
/* @__PURE__ */
|
|
807
|
+
children ? /* @__PURE__ */ jsx12(Grid3, { children }) : null,
|
|
808
|
+
/* @__PURE__ */ jsx12(Grid3, { children: /* @__PURE__ */ jsx12(
|
|
613
809
|
Dropzone,
|
|
614
810
|
{
|
|
615
811
|
name,
|
|
@@ -627,7 +823,7 @@ var FileSelector = ({
|
|
|
627
823
|
}
|
|
628
824
|
) })
|
|
629
825
|
] }),
|
|
630
|
-
fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */
|
|
826
|
+
fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */ jsx12(
|
|
631
827
|
ErrorAlert,
|
|
632
828
|
{
|
|
633
829
|
errors: rejection.errors,
|
|
@@ -637,7 +833,7 @@ var FileSelector = ({
|
|
|
637
833
|
},
|
|
638
834
|
rejection.id
|
|
639
835
|
)) : null,
|
|
640
|
-
/* @__PURE__ */
|
|
836
|
+
/* @__PURE__ */ jsx12(
|
|
641
837
|
FileList,
|
|
642
838
|
{
|
|
643
839
|
files: files || [],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@availity/mui-file-selector",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Availity MUI file-selector Component - part of the @availity/element design system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@availity/mui-alert": "^1.0.1",
|
|
45
45
|
"@availity/mui-button": "^1.0.1",
|
|
46
46
|
"@availity/mui-divider": "^1.0.1",
|
|
47
|
-
"@availity/mui-form-utils": "^1.0
|
|
47
|
+
"@availity/mui-form-utils": "^1.1.0",
|
|
48
48
|
"@availity/mui-icon": "^1.0.1",
|
|
49
49
|
"@availity/mui-layout": "^1.0.1",
|
|
50
50
|
"@availity/mui-list": "^1.0.1",
|
|
@@ -33,6 +33,21 @@ const meta: Meta<typeof FileSelector> = {
|
|
|
33
33
|
</QueryClientProvider>
|
|
34
34
|
),
|
|
35
35
|
],
|
|
36
|
+
args: {
|
|
37
|
+
name: 'file-selector',
|
|
38
|
+
allowedFileTypes: ['.txt', '.png', '.pdf'],
|
|
39
|
+
clientId: '123',
|
|
40
|
+
customerId: '456',
|
|
41
|
+
bucketId: '789',
|
|
42
|
+
uploadOptions: {
|
|
43
|
+
retryDelays: [],
|
|
44
|
+
},
|
|
45
|
+
maxFiles: 5,
|
|
46
|
+
maxSize: 1 * 1024 * 1024, // 1MB
|
|
47
|
+
enableDropArea: true,
|
|
48
|
+
isCloud: true,
|
|
49
|
+
multiple: true,
|
|
50
|
+
},
|
|
36
51
|
};
|
|
37
52
|
|
|
38
53
|
export default meta;
|
|
@@ -85,7 +100,91 @@ export const _FileSelector: StoryObj<typeof FileSelector> = {
|
|
|
85
100
|
</DismissableAlert>
|
|
86
101
|
</FileSelector>
|
|
87
102
|
{files.length > 0 && (
|
|
88
|
-
<Grid
|
|
103
|
+
<Grid size={{xs: 12}} justifyContent="end" display="flex" paddingTop={2.5}>
|
|
104
|
+
<Button type="submit" sx={{ marginLeft: 'auto', marginRight: 0 }}>
|
|
105
|
+
Submit
|
|
106
|
+
</Button>
|
|
107
|
+
</Grid>
|
|
108
|
+
)}
|
|
109
|
+
</form>
|
|
110
|
+
</FormProvider>
|
|
111
|
+
</Paper>
|
|
112
|
+
);
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/** Set `enableDropzone` to `false` for a button only file selector. */
|
|
117
|
+
export const _ButtonOnly: StoryObj<typeof FileSelector> = {
|
|
118
|
+
render: (props: FileSelectorProps) => {
|
|
119
|
+
const methods = useForm({
|
|
120
|
+
defaultValues: {
|
|
121
|
+
[props.name]: [] as File[],
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const client = useQueryClient();
|
|
126
|
+
|
|
127
|
+
const files = methods.watch(props.name);
|
|
128
|
+
|
|
129
|
+
const handleOnSubmit = (values: Record<string, File[]>) => {
|
|
130
|
+
if (values[props.name].length === 0) return;
|
|
131
|
+
|
|
132
|
+
const queries = client.getQueriesData<Upload>(['upload']);
|
|
133
|
+
const uploads = [];
|
|
134
|
+
for (const [, data] of queries) {
|
|
135
|
+
if (data) uploads.push(data);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<Paper sx={{ padding: '2rem' }}>
|
|
141
|
+
<FormProvider {...methods}>
|
|
142
|
+
<form onSubmit={methods.handleSubmit(handleOnSubmit)}>
|
|
143
|
+
<FileSelector {...props} enableDropArea={false}/>
|
|
144
|
+
{files.length > 0 && (
|
|
145
|
+
<Grid size={{xs: 12}} justifyContent="end" display="flex" paddingTop={2.5}>
|
|
146
|
+
<Button type="submit" sx={{ marginLeft: 'auto', marginRight: 0 }}>
|
|
147
|
+
Submit
|
|
148
|
+
</Button>
|
|
149
|
+
</Grid>
|
|
150
|
+
)}
|
|
151
|
+
</form>
|
|
152
|
+
</FormProvider>
|
|
153
|
+
</Paper>
|
|
154
|
+
);
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/** Upload password protected files. _For this example, the password for any file is '1234'_ */
|
|
159
|
+
export const _Encrypted: StoryObj<typeof FileSelector> = {
|
|
160
|
+
render: (props: Omit<FileSelectorProps, 'bucketId'>) => {
|
|
161
|
+
const methods = useForm({
|
|
162
|
+
defaultValues: {
|
|
163
|
+
[props.name]: [] as File[],
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const client = useQueryClient();
|
|
168
|
+
|
|
169
|
+
const files = methods.watch(props.name);
|
|
170
|
+
|
|
171
|
+
const handleOnSubmit = (values: Record<string, File[]>) => {
|
|
172
|
+
if (values[props.name].length === 0) return;
|
|
173
|
+
|
|
174
|
+
const queries = client.getQueriesData<Upload>(['upload']);
|
|
175
|
+
const uploads = [];
|
|
176
|
+
for (const [, data] of queries) {
|
|
177
|
+
if (data) uploads.push(data);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<Paper sx={{ padding: '2rem' }}>
|
|
183
|
+
<FormProvider {...methods}>
|
|
184
|
+
<form onSubmit={methods.handleSubmit(handleOnSubmit)}>
|
|
185
|
+
<FileSelector {...props} bucketId="enc"/>
|
|
186
|
+
{files.length > 0 && (
|
|
187
|
+
<Grid size={{xs: 12}} justifyContent="end" display="flex" paddingTop={2.5}>
|
|
89
188
|
<Button type="submit" sx={{ marginLeft: 'auto', marginRight: 0 }}>
|
|
90
189
|
Submit
|
|
91
190
|
</Button>
|
|
@@ -97,18 +196,9 @@ export const _FileSelector: StoryObj<typeof FileSelector> = {
|
|
|
97
196
|
);
|
|
98
197
|
},
|
|
99
198
|
args: {
|
|
100
|
-
|
|
101
|
-
allowedFileTypes: ['.txt', '.png', '.pdf'],
|
|
102
|
-
clientId: '123',
|
|
103
|
-
customerId: '456',
|
|
104
|
-
bucketId: '789',
|
|
105
|
-
uploadOptions: {
|
|
106
|
-
retryDelays: [],
|
|
107
|
-
},
|
|
108
|
-
maxFiles: 5,
|
|
109
|
-
maxSize: 1 * 1024 * 1024, // 1MB
|
|
110
|
-
enableDropArea: true,
|
|
111
|
-
isCloud: true,
|
|
112
|
-
multiple: true,
|
|
199
|
+
bucketId: 'enc'
|
|
113
200
|
},
|
|
201
|
+
argTypes: {
|
|
202
|
+
bucketId: { control: false }
|
|
203
|
+
}
|
|
114
204
|
};
|
|
@@ -37,4 +37,22 @@ describe('UploadProgressBar', () => {
|
|
|
37
37
|
|
|
38
38
|
expect(screen.getByText('error message')).toBeTruthy();
|
|
39
39
|
});
|
|
40
|
+
|
|
41
|
+
test('should allow passwords for encrypted files', () => {
|
|
42
|
+
const mockUpload: unknown = {
|
|
43
|
+
onProgress: [],
|
|
44
|
+
onError: [],
|
|
45
|
+
onSuccess: [],
|
|
46
|
+
errorMessage: 'error message',
|
|
47
|
+
file: {
|
|
48
|
+
name: 'test',
|
|
49
|
+
},
|
|
50
|
+
status: 'encrypted'
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
render(<UploadProgressBar upload={mockUpload as Upload} />);
|
|
54
|
+
|
|
55
|
+
expect(screen.getByText('error message')).toBeTruthy();
|
|
56
|
+
expect(screen.getByText('Enter Password')).toBeTruthy();
|
|
57
|
+
});
|
|
40
58
|
});
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { ChangeEvent, FormEventHandler, useState } from 'react';
|
|
2
|
+
import { Button, IconButton } from '@availity/mui-button';
|
|
3
|
+
import { Dialog, DialogActions, DialogContent, DialogTitle } from '@availity/mui-dialog';
|
|
4
|
+
import { InputAdornment } from '@availity/mui-form-utils';
|
|
5
|
+
import { EyeIcon, EyeSlashIcon, WarningTriangleIcon } from '@availity/mui-icon';
|
|
6
|
+
import { Box } from '@availity/mui-layout';
|
|
7
|
+
import { ListItemText } from '@availity/mui-list';
|
|
2
8
|
import { LinearProgress } from '@availity/mui-progress';
|
|
9
|
+
import { TextField } from '@availity/mui-textfield';
|
|
3
10
|
import type Upload from '@availity/upload-core';
|
|
4
|
-
import { WarningTriangleIcon } from '@availity/mui-icon';
|
|
5
|
-
import { ListItemText } from '@availity/mui-list';
|
|
6
11
|
|
|
7
12
|
export type UploadProgressBarProps = {
|
|
8
13
|
/**
|
|
@@ -25,75 +30,90 @@ export type UploadProgressBarProps = {
|
|
|
25
30
|
|
|
26
31
|
export const UploadProgressBar = ({ upload, onProgress, onError, onSuccess }: UploadProgressBarProps) => {
|
|
27
32
|
const [statePercentage, setStatePercentage] = useState(upload.percentage || 0);
|
|
28
|
-
const [
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
const [errorMessage, setErrorMessage] = useState(upload.errorMessage || '');
|
|
34
|
+
const [password, setPassword] = useState('');
|
|
35
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
36
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
31
37
|
|
|
32
38
|
const handleOnProgress = () => {
|
|
33
39
|
setStatePercentage(upload.percentage);
|
|
34
|
-
|
|
40
|
+
setErrorMessage('');
|
|
35
41
|
|
|
36
42
|
if (onProgress) onProgress(upload);
|
|
37
43
|
};
|
|
38
44
|
|
|
39
45
|
const handleOnError = () => {
|
|
40
|
-
|
|
46
|
+
setErrorMessage(upload.errorMessage || 'Error');
|
|
41
47
|
|
|
42
48
|
if (onError) onError(upload);
|
|
43
49
|
};
|
|
44
50
|
|
|
45
51
|
const handleOnSuccess = () => {
|
|
46
52
|
setStatePercentage(100);
|
|
47
|
-
|
|
53
|
+
setErrorMessage('');
|
|
48
54
|
|
|
49
55
|
if (onSuccess) onSuccess(upload);
|
|
50
56
|
};
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
const toggleModal = () => {
|
|
59
|
+
setModalOpen((prev) => !prev);
|
|
60
|
+
setPassword('');
|
|
61
|
+
};
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
const verifyPassword: FormEventHandler<HTMLFormElement> = (event) => {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
event.stopPropagation();
|
|
66
|
+
upload.sendPassword(password);
|
|
67
|
+
toggleModal();
|
|
68
|
+
};
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
|
|
71
|
+
setPassword(event.target.value);
|
|
72
|
+
};
|
|
67
73
|
|
|
68
74
|
upload.onProgress.push(handleOnProgress);
|
|
69
75
|
upload.onSuccess.push(handleOnSuccess);
|
|
70
76
|
upload.onError.push(handleOnError);
|
|
71
77
|
|
|
72
|
-
return
|
|
73
|
-
|
|
74
|
-
<ListItemText
|
|
75
|
-
<WarningTriangleIcon /> {
|
|
78
|
+
return errorMessage ? (
|
|
79
|
+
<Box sx={{display: 'flex', flexWrap: 'wrap', columnGap: '4px'}}>
|
|
80
|
+
<ListItemText slotProps={{primary: { color: 'text.error', variant: 'body2', component: 'div' }}}>
|
|
81
|
+
<WarningTriangleIcon sx={{verticalAlign: 'middle', mt: '-2px'}}/> {errorMessage}
|
|
76
82
|
</ListItemText>
|
|
77
|
-
{
|
|
83
|
+
{upload.status === 'encrypted' && (
|
|
78
84
|
<div className="pwRequired">
|
|
79
|
-
<Button color="
|
|
80
|
-
Enter
|
|
85
|
+
<Button color="secondary" size="small" onClick={toggleModal}>
|
|
86
|
+
Enter Password
|
|
81
87
|
</Button>
|
|
82
|
-
<
|
|
88
|
+
<Dialog open={modalOpen} onClose={toggleModal}>
|
|
83
89
|
<form onSubmit={verifyPassword}>
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
<DialogTitle>Enter Password</DialogTitle>
|
|
91
|
+
<DialogContent>
|
|
92
|
+
<TextField
|
|
93
|
+
type={showPassword ? 'text' : 'password'}
|
|
94
|
+
name="upload-password"
|
|
95
|
+
label="Password"
|
|
96
|
+
onChange={handlePasswordChange}
|
|
97
|
+
autoFocus
|
|
98
|
+
InputProps={{
|
|
99
|
+
endAdornment: (
|
|
100
|
+
<InputAdornment position="end">
|
|
101
|
+
<IconButton title="password visibility" onClick={() => setShowPassword((prev) => !prev)} edge="end">
|
|
102
|
+
{showPassword ? <EyeIcon fontSize="small" /> : <EyeSlashIcon fontSize="small" />}
|
|
103
|
+
</IconButton>
|
|
104
|
+
</InputAdornment>
|
|
105
|
+
),
|
|
106
|
+
}}
|
|
107
|
+
/>
|
|
108
|
+
</DialogContent>
|
|
109
|
+
<DialogActions>
|
|
110
|
+
<Button color="primary" type="submit">Ok</Button>
|
|
111
|
+
</DialogActions>
|
|
92
112
|
</form>
|
|
93
|
-
</
|
|
113
|
+
</Dialog>
|
|
94
114
|
</div>
|
|
95
|
-
)}
|
|
96
|
-
|
|
115
|
+
)}
|
|
116
|
+
</Box>
|
|
97
117
|
) : (
|
|
98
118
|
<LinearProgress value={statePercentage} aria-label={`${upload.file.name}-progress`} />
|
|
99
119
|
);
|