@availity/mui-file-selector 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ## [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)
6
+
7
+
8
+ ### Features
9
+
10
+ * **mui-file-selector:** add encrypted file support ([831383d](https://github.com/Availity/element/commit/831383d7c1470f0fbb086b40f268a60925268656))
11
+
12
+ ## [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)
13
+
5
14
  ## [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)
6
15
 
7
16
  ### Dependency Updates
package/dist/index.js CHANGED
@@ -347,46 +347,189 @@ 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 import_mui_button2 = require("@availity/mui-button");
351
- var import_mui_icon4 = require("@availity/mui-icon");
352
- var import_mui_layout2 = require("@availity/mui-layout");
350
+ var import_mui_button4 = require("@availity/mui-button");
351
+ var import_mui_icon5 = require("@availity/mui-icon");
352
+ var import_mui_layout3 = require("@availity/mui-layout");
353
353
  var import_mui_divider2 = require("@availity/mui-divider");
354
354
 
355
355
  // src/lib/UploadProgressBar.tsx
356
- var import_react2 = require("react");
357
- var import_mui_progress = require("@availity/mui-progress");
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_layout2 = 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_jsx_runtime9 = require("react/jsx-runtime");
441
+ var TextField = (0, import_react2.forwardRef)((props, ref) => {
442
+ const _a = props, { InputProps: InputProps2, helpTopicId, InputLabelProps, FormHelperTextProps: FormHelperTextProps2, required, SelectProps: SelectProps2, inputProps } = _a, rest = __objRest(_a, ["InputProps", "helpTopicId", "InputLabelProps", "FormHelperTextProps", "required", "SelectProps", "inputProps"]);
443
+ const [openDetected, setOpenDetected] = (0, import_react2.useState)(false);
444
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
445
+ import_TextField.default,
446
+ __spreadProps(__spreadValues({}, rest), {
447
+ slotProps: {
448
+ input: __spreadValues(__spreadValues({}, InputProps2), import_mui_form_utils2.InputPropOverrides),
449
+ htmlInput: __spreadValues({ "aria-required": required }, inputProps),
450
+ select: __spreadValues(__spreadValues(__spreadValues({}, SelectProps2), import_mui_form_utils2.SelectPropOverrides), (0, import_mui_form_utils2.SelectAccessibilityOverrides)(openDetected, setOpenDetected, SelectProps2 == null ? void 0 : SelectProps2.open)),
451
+ inputLabel: __spreadValues({
452
+ component: import_mui_form_utils2.FormLabel,
453
+ helpTopicId,
454
+ required,
455
+ shrink: true
456
+ }, InputLabelProps),
457
+ formHelperText: __spreadValues({ component: import_mui_form_utils2.FormHelperText }, FormHelperTextProps2)
458
+ },
459
+ ref
460
+ })
461
+ );
462
+ });
463
+
464
+ // src/lib/UploadProgressBar.tsx
465
+ var import_jsx_runtime10 = require("react/jsx-runtime");
361
466
  var UploadProgressBar = ({ upload, onProgress, onError, onSuccess }) => {
362
- const [statePercentage, setStatePercentage] = (0, import_react2.useState)(upload.percentage || 0);
363
- const [error, setError] = (0, import_react2.useState)(false);
467
+ const [statePercentage, setStatePercentage] = (0, import_react3.useState)(upload.percentage || 0);
468
+ const [errorMessage, setErrorMessage] = (0, import_react3.useState)(upload.errorMessage || "");
469
+ const [password, setPassword] = (0, import_react3.useState)("");
470
+ const [showPassword, setShowPassword] = (0, import_react3.useState)(false);
471
+ const [modalOpen, setModalOpen] = (0, import_react3.useState)(false);
364
472
  const handleOnProgress = () => {
365
473
  setStatePercentage(upload.percentage);
366
- setError(false);
474
+ setErrorMessage("");
367
475
  if (onProgress) onProgress(upload);
368
476
  };
369
477
  const handleOnError = () => {
370
- setError(true);
478
+ setErrorMessage(upload.errorMessage || "Error");
371
479
  if (onError) onError(upload);
372
480
  };
373
481
  const handleOnSuccess = () => {
374
482
  setStatePercentage(100);
375
- setError(false);
483
+ setErrorMessage("");
376
484
  if (onSuccess) onSuccess(upload);
377
485
  };
486
+ const toggleModal = () => {
487
+ setModalOpen((prev) => !prev);
488
+ setPassword("");
489
+ };
490
+ const verifyPassword = (event) => {
491
+ event.preventDefault();
492
+ event.stopPropagation();
493
+ upload.sendPassword(password);
494
+ toggleModal();
495
+ };
496
+ const handlePasswordChange = (event) => {
497
+ setPassword(event.target.value);
498
+ };
378
499
  upload.onProgress.push(handleOnProgress);
379
500
  upload.onSuccess.push(handleOnSuccess);
380
501
  upload.onError.push(handleOnError);
381
- return upload.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_mui_list.ListItemText, { primaryTypographyProps: { color: "text.error", variant: "body2" }, children: [
382
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_mui_icon2.WarningTriangleIcon, {}),
383
- " ",
384
- upload.errorMessage
385
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_mui_progress.LinearProgress, { value: statePercentage, "aria-label": `${upload.file.name}-progress` });
502
+ return errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_mui_layout2.Box, { sx: { display: "flex", flexWrap: "wrap", columnGap: "4px" }, children: [
503
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_mui_list.ListItemText, { slotProps: { primary: { color: "text.error", variant: "body2", component: "div" } }, children: [
504
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_icon3.WarningTriangleIcon, { sx: { verticalAlign: "middle", mt: "-2px" } }),
505
+ " ",
506
+ errorMessage
507
+ ] }),
508
+ upload.status === "encrypted" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "pwRequired", children: [
509
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_button3.Button, { color: "secondary", size: "small", onClick: toggleModal, children: "Enter Password" }),
510
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Dialog, { open: modalOpen, onClose: toggleModal, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("form", { onSubmit: verifyPassword, children: [
511
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogTitle, { children: "Enter Password" }),
512
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
513
+ TextField,
514
+ {
515
+ type: showPassword ? "text" : "password",
516
+ name: "upload-password",
517
+ label: "Password",
518
+ onChange: handlePasswordChange,
519
+ autoFocus: true,
520
+ InputProps: {
521
+ 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" }) }) })
522
+ }
523
+ }
524
+ ) }),
525
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(DialogActions, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_button3.Button, { color: "primary", type: "submit", children: "Ok" }) })
526
+ ] }) })
527
+ ] })
528
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_mui_progress.LinearProgress, { value: statePercentage, "aria-label": `${upload.file.name}-progress` });
386
529
  };
387
530
 
388
531
  // src/lib/util.ts
389
- var import_mui_icon3 = require("@availity/mui-icon");
532
+ var import_mui_icon4 = require("@availity/mui-icon");
390
533
  function formatBytes(bytes, decimals = 2) {
391
534
  if (!+bytes) return "0 Bytes";
392
535
  const k = 1024;
@@ -396,30 +539,30 @@ function formatBytes(bytes, decimals = 2) {
396
539
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
397
540
  }
398
541
  var FILE_EXT_ICONS = {
399
- png: import_mui_icon3.FileImageIcon,
400
- jpg: import_mui_icon3.FileImageIcon,
401
- jpeg: import_mui_icon3.FileImageIcon,
402
- gif: import_mui_icon3.FileImageIcon,
403
- csv: import_mui_icon3.FileCsvIcon,
404
- ppt: import_mui_icon3.FilePowerpointIcon,
405
- pptx: import_mui_icon3.FilePowerpointIcon,
406
- xls: import_mui_icon3.FileExcelIcon,
407
- xlsx: import_mui_icon3.FileExcelIcon,
408
- doc: import_mui_icon3.FileWordIcon,
409
- docx: import_mui_icon3.FileWordIcon,
410
- txt: import_mui_icon3.FileLinesIcon,
411
- text: import_mui_icon3.FileLinesIcon,
412
- zip: import_mui_icon3.FileArchiveIcon,
413
- "7zip": import_mui_icon3.FileArchiveIcon,
414
- xml: import_mui_icon3.FileCodeIcon,
415
- html: import_mui_icon3.FileCodeIcon,
416
- pdf: import_mui_icon3.FilePdfIcon
542
+ png: import_mui_icon4.FileImageIcon,
543
+ jpg: import_mui_icon4.FileImageIcon,
544
+ jpeg: import_mui_icon4.FileImageIcon,
545
+ gif: import_mui_icon4.FileImageIcon,
546
+ csv: import_mui_icon4.FileCsvIcon,
547
+ ppt: import_mui_icon4.FilePowerpointIcon,
548
+ pptx: import_mui_icon4.FilePowerpointIcon,
549
+ xls: import_mui_icon4.FileExcelIcon,
550
+ xlsx: import_mui_icon4.FileExcelIcon,
551
+ doc: import_mui_icon4.FileWordIcon,
552
+ docx: import_mui_icon4.FileWordIcon,
553
+ txt: import_mui_icon4.FileLinesIcon,
554
+ text: import_mui_icon4.FileLinesIcon,
555
+ zip: import_mui_icon4.FileArchiveIcon,
556
+ "7zip": import_mui_icon4.FileArchiveIcon,
557
+ xml: import_mui_icon4.FileCodeIcon,
558
+ html: import_mui_icon4.FileCodeIcon,
559
+ pdf: import_mui_icon4.FilePdfIcon
417
560
  };
418
561
  var isValidKey = (key) => key ? key in FILE_EXT_ICONS : false;
419
562
  var getFileExtIcon = (fileName) => {
420
563
  var _a;
421
564
  const ext = ((_a = fileName.split(".").pop()) == null ? void 0 : _a.toLowerCase()) || "";
422
- const icon = isValidKey(ext) ? FILE_EXT_ICONS[ext] : import_mui_icon3.FileIcon;
565
+ const icon = isValidKey(ext) ? FILE_EXT_ICONS[ext] : import_mui_icon4.FileIcon;
423
566
  return icon;
424
567
  };
425
568
 
@@ -449,7 +592,7 @@ function useUploadCore(file, options, queryOptions) {
449
592
  }
450
593
 
451
594
  // src/lib/FileList.tsx
452
- var import_jsx_runtime5 = require("react/jsx-runtime");
595
+ var import_jsx_runtime11 = require("react/jsx-runtime");
453
596
  var FileRow = ({
454
597
  file,
455
598
  options,
@@ -460,31 +603,31 @@ var FileRow = ({
460
603
  }) => {
461
604
  const Icon = getFileExtIcon(file.name);
462
605
  const { data: upload } = useUploadCore(file, options, queryOptions);
463
- if (CustomRow) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CustomRow, { upload, options, onRemoveFile });
606
+ if (CustomRow) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CustomRow, { upload, options, onRemoveFile });
464
607
  if (!upload) return null;
465
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
608
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
466
609
  import_mui_list2.ListItem,
467
610
  {
468
611
  disableGutters: true,
469
- secondaryAction: !disableRemove && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
470
- import_mui_button2.IconButton,
612
+ secondaryAction: !disableRemove && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
613
+ import_mui_button4.IconButton,
471
614
  {
472
615
  title: "remove file",
473
616
  edge: "end",
474
617
  onClick: () => {
475
618
  onRemoveFile(upload.id, upload);
476
619
  },
477
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_icon4.DeleteIcon, {})
620
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_icon5.DeleteIcon, {})
478
621
  }
479
622
  ),
480
623
  children: [
481
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_mui_layout2.Grid, { container: true, spacing: 2, alignItems: "center", justifyContent: "space-between", width: "100%", children: [
482
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_layout2.Grid, { size: { xs: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_list2.ListItemIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, {}) }) }),
483
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_layout2.Grid, { size: { xs: 3 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_list2.ListItemText, { children: upload.trimFileName(upload.file.name) }) }),
484
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_layout2.Grid, { size: { xs: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_list2.ListItemText, { children: formatBytes(upload.file.size) }) }),
485
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_layout2.Grid, { size: { xs: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UploadProgressBar, { upload }) })
624
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_mui_layout3.Grid, { container: true, spacing: 2, alignItems: "center", justifyContent: "space-between", width: "100%", children: [
625
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout3.Grid, { size: { xs: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.ListItemIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Icon, {}) }) }),
626
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout3.Grid, { size: { xs: 3 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.ListItemText, { children: upload.trimFileName(upload.file.name) }) }),
627
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout3.Grid, { size: { xs: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.ListItemText, { children: formatBytes(upload.file.size) }) }),
628
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_layout3.Grid, { size: { xs: 6 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(UploadProgressBar, { upload }) })
486
629
  ] }),
487
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_divider2.Divider, {})
630
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_divider2.Divider, {})
488
631
  ]
489
632
  }
490
633
  );
@@ -498,8 +641,8 @@ var FileList = ({
498
641
  disableRemove
499
642
  }) => {
500
643
  if (files.length === 0) return null;
501
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_mui_list2.List, { children: files.map((file) => {
502
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
644
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_mui_list2.List, { children: files.map((file) => {
645
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
503
646
  FileRow,
504
647
  {
505
648
  file,
@@ -515,15 +658,15 @@ var FileList = ({
515
658
  };
516
659
 
517
660
  // src/lib/FileSelector.tsx
518
- var import_react3 = require("react");
661
+ var import_react4 = require("react");
519
662
  var import_react_hook_form3 = require("react-hook-form");
520
663
  var import_react_query2 = require("@tanstack/react-query");
521
- var import_mui_layout3 = require("@availity/mui-layout");
664
+ var import_mui_layout4 = require("@availity/mui-layout");
522
665
  var import_mui_typography4 = require("@availity/mui-typography");
523
666
 
524
667
  // src/lib/FileTypesMessage.tsx
525
668
  var import_mui_typography2 = require("@availity/mui-typography");
526
- var import_jsx_runtime6 = require("react/jsx-runtime");
669
+ var import_jsx_runtime12 = require("react/jsx-runtime");
527
670
  var FileTypesMessage = ({
528
671
  allowedFileTypes = [],
529
672
  maxFileSize,
@@ -531,7 +674,7 @@ var FileTypesMessage = ({
531
674
  }) => {
532
675
  const fileSizeMsg = typeof maxFileSize === "number" ? `Maximum file size is ${formatBytes(maxFileSize)}. ` : null;
533
676
  const fileTypesMsg = allowedFileTypes.length > 0 ? `Supported file types include: ${allowedFileTypes.join(", ")}` : "All file types allowed.";
534
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_mui_typography2.Typography, { variant, children: [
677
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_mui_typography2.Typography, { variant, children: [
535
678
  fileSizeMsg,
536
679
  fileTypesMsg
537
680
  ] });
@@ -539,9 +682,9 @@ var FileTypesMessage = ({
539
682
 
540
683
  // src/lib/HeaderMessage.tsx
541
684
  var import_mui_typography3 = require("@availity/mui-typography");
542
- var import_jsx_runtime7 = require("react/jsx-runtime");
685
+ var import_jsx_runtime13 = require("react/jsx-runtime");
543
686
  var HeaderMessage = ({ maxFiles, maxSize }) => {
544
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_mui_typography3.Typography, { variant: "h6", children: [
687
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_mui_typography3.Typography, { variant: "h6", children: [
545
688
  "Attach up to ",
546
689
  maxFiles,
547
690
  " file(s), with a maximum individual size of ",
@@ -550,7 +693,7 @@ var HeaderMessage = ({ maxFiles, maxSize }) => {
550
693
  };
551
694
 
552
695
  // src/lib/FileSelector.tsx
553
- var import_jsx_runtime8 = require("react/jsx-runtime");
696
+ var import_jsx_runtime14 = require("react/jsx-runtime");
554
697
  var CLOUD_URL = "/cloud/web/appl/vault/upload/v1/resumable";
555
698
  var FileSelector = ({
556
699
  name,
@@ -577,8 +720,8 @@ var FileSelector = ({
577
720
  validator,
578
721
  disableRemove
579
722
  }) => {
580
- const [totalSize, setTotalSize] = (0, import_react3.useState)(0);
581
- const [fileRejections, setFileRejections] = (0, import_react3.useState)([]);
723
+ const [totalSize, setTotalSize] = (0, import_react4.useState)(0);
724
+ const [fileRejections, setFileRejections] = (0, import_react4.useState)([]);
582
725
  const client = (0, import_react_query2.useQueryClient)();
583
726
  const formMethods = (0, import_react_hook_form3.useFormContext)();
584
727
  const options = __spreadProps(__spreadValues({}, uploadOptions), {
@@ -612,10 +755,10 @@ var FileSelector = ({
612
755
  const rejections = fileRejections.filter((value) => value.id !== id);
613
756
  setFileRejections(rejections);
614
757
  };
615
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
616
- enableDropArea ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
617
- label ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_mui_typography4.Typography, { marginBottom: "4px", children: label }) : null,
618
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
758
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
759
+ enableDropArea ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
760
+ label ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_mui_typography4.Typography, { marginBottom: "4px", children: label }) : null,
761
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
619
762
  Dropzone,
620
763
  {
621
764
  name,
@@ -632,15 +775,15 @@ var FileSelector = ({
632
775
  validator
633
776
  }
634
777
  ),
635
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FileTypesMessage, { allowedFileTypes, maxFileSize: maxSize, variant: "caption" }),
778
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FileTypesMessage, { allowedFileTypes, maxFileSize: maxSize, variant: "caption" }),
636
779
  children
637
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_mui_layout3.Grid, { container: true, rowSpacing: 3, flexDirection: "column", children: [
638
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_mui_layout3.Grid, { children: [
639
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(HeaderMessage, { maxFiles, maxSize }),
640
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FileTypesMessage, { allowedFileTypes, variant: "body2" })
780
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_mui_layout4.Grid, { container: true, rowSpacing: 3, flexDirection: "column", children: [
781
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_mui_layout4.Grid, { children: [
782
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(HeaderMessage, { maxFiles, maxSize }),
783
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FileTypesMessage, { allowedFileTypes, variant: "body2" })
641
784
  ] }),
642
- children ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_mui_layout3.Grid, { children }) : null,
643
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_mui_layout3.Grid, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
785
+ children ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_mui_layout4.Grid, { children }) : null,
786
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_mui_layout4.Grid, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
644
787
  Dropzone,
645
788
  {
646
789
  name,
@@ -658,7 +801,7 @@ var FileSelector = ({
658
801
  }
659
802
  ) })
660
803
  ] }),
661
- fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
804
+ fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
662
805
  ErrorAlert,
663
806
  {
664
807
  errors: rejection.errors,
@@ -668,7 +811,7 @@ var FileSelector = ({
668
811
  },
669
812
  rejection.id
670
813
  )) : null,
671
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
814
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
672
815
  FileList,
673
816
  {
674
817
  files: files || [],
package/dist/index.mjs CHANGED
@@ -305,42 +305,191 @@ 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
310
  import { Grid } 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 { LinearProgress } from "@availity/mui-progress";
316
- import { WarningTriangleIcon } from "@availity/mui-icon";
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 { Fragment as Fragment4, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
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 { jsx as jsx9 } from "react/jsx-runtime";
405
+ var TextField = forwardRef((props, ref) => {
406
+ const _a = props, { InputProps: InputProps2, helpTopicId, InputLabelProps, FormHelperTextProps: FormHelperTextProps2, required, SelectProps: SelectProps2, inputProps } = _a, rest = __objRest(_a, ["InputProps", "helpTopicId", "InputLabelProps", "FormHelperTextProps", "required", "SelectProps", "inputProps"]);
407
+ const [openDetected, setOpenDetected] = useState(false);
408
+ return /* @__PURE__ */ jsx9(
409
+ MuiTextField,
410
+ __spreadProps(__spreadValues({}, rest), {
411
+ slotProps: {
412
+ input: __spreadValues(__spreadValues({}, InputProps2), InputPropOverrides),
413
+ htmlInput: __spreadValues({ "aria-required": required }, inputProps),
414
+ select: __spreadValues(__spreadValues(__spreadValues({}, SelectProps2), SelectPropOverrides), SelectAccessibilityOverrides(openDetected, setOpenDetected, SelectProps2 == null ? void 0 : SelectProps2.open)),
415
+ inputLabel: __spreadValues({
416
+ component: FormLabel,
417
+ helpTopicId,
418
+ required,
419
+ shrink: true
420
+ }, InputLabelProps),
421
+ formHelperText: __spreadValues({ component: FormHelperText }, FormHelperTextProps2)
422
+ },
423
+ ref
424
+ })
425
+ );
426
+ });
427
+
428
+ // src/lib/UploadProgressBar.tsx
429
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
319
430
  var UploadProgressBar = ({ upload, onProgress, onError, onSuccess }) => {
320
- const [statePercentage, setStatePercentage] = useState(upload.percentage || 0);
321
- const [error, setError] = useState(false);
431
+ const [statePercentage, setStatePercentage] = useState2(upload.percentage || 0);
432
+ const [errorMessage, setErrorMessage] = useState2(upload.errorMessage || "");
433
+ const [password, setPassword] = useState2("");
434
+ const [showPassword, setShowPassword] = useState2(false);
435
+ const [modalOpen, setModalOpen] = useState2(false);
322
436
  const handleOnProgress = () => {
323
437
  setStatePercentage(upload.percentage);
324
- setError(false);
438
+ setErrorMessage("");
325
439
  if (onProgress) onProgress(upload);
326
440
  };
327
441
  const handleOnError = () => {
328
- setError(true);
442
+ setErrorMessage(upload.errorMessage || "Error");
329
443
  if (onError) onError(upload);
330
444
  };
331
445
  const handleOnSuccess = () => {
332
446
  setStatePercentage(100);
333
- setError(false);
447
+ setErrorMessage("");
334
448
  if (onSuccess) onSuccess(upload);
335
449
  };
450
+ const toggleModal = () => {
451
+ setModalOpen((prev) => !prev);
452
+ setPassword("");
453
+ };
454
+ const verifyPassword = (event) => {
455
+ event.preventDefault();
456
+ event.stopPropagation();
457
+ upload.sendPassword(password);
458
+ toggleModal();
459
+ };
460
+ const handlePasswordChange = (event) => {
461
+ setPassword(event.target.value);
462
+ };
336
463
  upload.onProgress.push(handleOnProgress);
337
464
  upload.onSuccess.push(handleOnSuccess);
338
465
  upload.onError.push(handleOnError);
339
- return upload.errorMessage ? /* @__PURE__ */ jsx4(Fragment4, { children: /* @__PURE__ */ jsxs4(ListItemText, { primaryTypographyProps: { color: "text.error", variant: "body2" }, children: [
340
- /* @__PURE__ */ jsx4(WarningTriangleIcon, {}),
341
- " ",
342
- upload.errorMessage
343
- ] }) }) : /* @__PURE__ */ jsx4(LinearProgress, { value: statePercentage, "aria-label": `${upload.file.name}-progress` });
466
+ return errorMessage ? /* @__PURE__ */ jsxs6(Box2, { sx: { display: "flex", flexWrap: "wrap", columnGap: "4px" }, children: [
467
+ /* @__PURE__ */ jsxs6(ListItemText, { slotProps: { primary: { color: "text.error", variant: "body2", component: "div" } }, children: [
468
+ /* @__PURE__ */ jsx10(WarningTriangleIcon, { sx: { verticalAlign: "middle", mt: "-2px" } }),
469
+ " ",
470
+ errorMessage
471
+ ] }),
472
+ upload.status === "encrypted" && /* @__PURE__ */ jsxs6("div", { className: "pwRequired", children: [
473
+ /* @__PURE__ */ jsx10(Button2, { color: "secondary", size: "small", onClick: toggleModal, children: "Enter Password" }),
474
+ /* @__PURE__ */ jsx10(Dialog, { open: modalOpen, onClose: toggleModal, children: /* @__PURE__ */ jsxs6("form", { onSubmit: verifyPassword, children: [
475
+ /* @__PURE__ */ jsx10(DialogTitle, { children: "Enter Password" }),
476
+ /* @__PURE__ */ jsx10(DialogContent, { children: /* @__PURE__ */ jsx10(
477
+ TextField,
478
+ {
479
+ type: showPassword ? "text" : "password",
480
+ name: "upload-password",
481
+ label: "Password",
482
+ onChange: handlePasswordChange,
483
+ autoFocus: true,
484
+ InputProps: {
485
+ 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" }) }) })
486
+ }
487
+ }
488
+ ) }),
489
+ /* @__PURE__ */ jsx10(DialogActions, { children: /* @__PURE__ */ jsx10(Button2, { color: "primary", type: "submit", children: "Ok" }) })
490
+ ] }) })
491
+ ] })
492
+ ] }) : /* @__PURE__ */ jsx10(LinearProgress, { value: statePercentage, "aria-label": `${upload.file.name}-progress` });
344
493
  };
345
494
 
346
495
  // src/lib/util.ts
@@ -418,7 +567,7 @@ function useUploadCore(file, options, queryOptions) {
418
567
  }
419
568
 
420
569
  // src/lib/FileList.tsx
421
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
570
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
422
571
  var FileRow = ({
423
572
  file,
424
573
  options,
@@ -429,31 +578,31 @@ var FileRow = ({
429
578
  }) => {
430
579
  const Icon = getFileExtIcon(file.name);
431
580
  const { data: upload } = useUploadCore(file, options, queryOptions);
432
- if (CustomRow) return /* @__PURE__ */ jsx5(CustomRow, { upload, options, onRemoveFile });
581
+ if (CustomRow) return /* @__PURE__ */ jsx11(CustomRow, { upload, options, onRemoveFile });
433
582
  if (!upload) return null;
434
- return /* @__PURE__ */ jsxs5(
583
+ return /* @__PURE__ */ jsxs7(
435
584
  ListItem,
436
585
  {
437
586
  disableGutters: true,
438
- secondaryAction: !disableRemove && /* @__PURE__ */ jsx5(
439
- IconButton,
587
+ secondaryAction: !disableRemove && /* @__PURE__ */ jsx11(
588
+ IconButton3,
440
589
  {
441
590
  title: "remove file",
442
591
  edge: "end",
443
592
  onClick: () => {
444
593
  onRemoveFile(upload.id, upload);
445
594
  },
446
- children: /* @__PURE__ */ jsx5(DeleteIcon, {})
595
+ children: /* @__PURE__ */ jsx11(DeleteIcon, {})
447
596
  }
448
597
  ),
449
598
  children: [
450
- /* @__PURE__ */ jsxs5(Grid, { container: true, spacing: 2, alignItems: "center", justifyContent: "space-between", width: "100%", children: [
451
- /* @__PURE__ */ jsx5(Grid, { size: { xs: 1 }, children: /* @__PURE__ */ jsx5(ListItemIcon, { children: /* @__PURE__ */ jsx5(Icon, {}) }) }),
452
- /* @__PURE__ */ jsx5(Grid, { size: { xs: 3 }, children: /* @__PURE__ */ jsx5(ListItemText2, { children: upload.trimFileName(upload.file.name) }) }),
453
- /* @__PURE__ */ jsx5(Grid, { size: { xs: 2 }, children: /* @__PURE__ */ jsx5(ListItemText2, { children: formatBytes(upload.file.size) }) }),
454
- /* @__PURE__ */ jsx5(Grid, { size: { xs: 6 }, children: /* @__PURE__ */ jsx5(UploadProgressBar, { upload }) })
599
+ /* @__PURE__ */ jsxs7(Grid, { container: true, spacing: 2, alignItems: "center", justifyContent: "space-between", width: "100%", children: [
600
+ /* @__PURE__ */ jsx11(Grid, { size: { xs: 1 }, children: /* @__PURE__ */ jsx11(ListItemIcon, { children: /* @__PURE__ */ jsx11(Icon, {}) }) }),
601
+ /* @__PURE__ */ jsx11(Grid, { size: { xs: 3 }, children: /* @__PURE__ */ jsx11(ListItemText2, { children: upload.trimFileName(upload.file.name) }) }),
602
+ /* @__PURE__ */ jsx11(Grid, { size: { xs: 2 }, children: /* @__PURE__ */ jsx11(ListItemText2, { children: formatBytes(upload.file.size) }) }),
603
+ /* @__PURE__ */ jsx11(Grid, { size: { xs: 6 }, children: /* @__PURE__ */ jsx11(UploadProgressBar, { upload }) })
455
604
  ] }),
456
- /* @__PURE__ */ jsx5(Divider2, {})
605
+ /* @__PURE__ */ jsx11(Divider2, {})
457
606
  ]
458
607
  }
459
608
  );
@@ -467,8 +616,8 @@ var FileList = ({
467
616
  disableRemove
468
617
  }) => {
469
618
  if (files.length === 0) return null;
470
- return /* @__PURE__ */ jsx5(List, { children: files.map((file) => {
471
- return /* @__PURE__ */ jsx5(
619
+ return /* @__PURE__ */ jsx11(List, { children: files.map((file) => {
620
+ return /* @__PURE__ */ jsx11(
472
621
  FileRow,
473
622
  {
474
623
  file,
@@ -484,7 +633,7 @@ var FileList = ({
484
633
  };
485
634
 
486
635
  // src/lib/FileSelector.tsx
487
- import { useState as useState2 } from "react";
636
+ import { useState as useState3 } from "react";
488
637
  import { useFormContext as useFormContext2 } from "react-hook-form";
489
638
  import { useQueryClient } from "@tanstack/react-query";
490
639
  import { Grid as Grid2 } from "@availity/mui-layout";
@@ -492,7 +641,7 @@ import { Typography as Typography4 } from "@availity/mui-typography";
492
641
 
493
642
  // src/lib/FileTypesMessage.tsx
494
643
  import { Typography as Typography2 } from "@availity/mui-typography";
495
- import { jsxs as jsxs6 } from "react/jsx-runtime";
644
+ import { jsxs as jsxs8 } from "react/jsx-runtime";
496
645
  var FileTypesMessage = ({
497
646
  allowedFileTypes = [],
498
647
  maxFileSize,
@@ -500,7 +649,7 @@ var FileTypesMessage = ({
500
649
  }) => {
501
650
  const fileSizeMsg = typeof maxFileSize === "number" ? `Maximum file size is ${formatBytes(maxFileSize)}. ` : null;
502
651
  const fileTypesMsg = allowedFileTypes.length > 0 ? `Supported file types include: ${allowedFileTypes.join(", ")}` : "All file types allowed.";
503
- return /* @__PURE__ */ jsxs6(Typography2, { variant, children: [
652
+ return /* @__PURE__ */ jsxs8(Typography2, { variant, children: [
504
653
  fileSizeMsg,
505
654
  fileTypesMsg
506
655
  ] });
@@ -508,9 +657,9 @@ var FileTypesMessage = ({
508
657
 
509
658
  // src/lib/HeaderMessage.tsx
510
659
  import { Typography as Typography3 } from "@availity/mui-typography";
511
- import { jsxs as jsxs7 } from "react/jsx-runtime";
660
+ import { jsxs as jsxs9 } from "react/jsx-runtime";
512
661
  var HeaderMessage = ({ maxFiles, maxSize }) => {
513
- return /* @__PURE__ */ jsxs7(Typography3, { variant: "h6", children: [
662
+ return /* @__PURE__ */ jsxs9(Typography3, { variant: "h6", children: [
514
663
  "Attach up to ",
515
664
  maxFiles,
516
665
  " file(s), with a maximum individual size of ",
@@ -519,7 +668,7 @@ var HeaderMessage = ({ maxFiles, maxSize }) => {
519
668
  };
520
669
 
521
670
  // src/lib/FileSelector.tsx
522
- import { Fragment as Fragment5, jsx as jsx6, jsxs as jsxs8 } from "react/jsx-runtime";
671
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
523
672
  var CLOUD_URL = "/cloud/web/appl/vault/upload/v1/resumable";
524
673
  var FileSelector = ({
525
674
  name,
@@ -546,8 +695,8 @@ var FileSelector = ({
546
695
  validator,
547
696
  disableRemove
548
697
  }) => {
549
- const [totalSize, setTotalSize] = useState2(0);
550
- const [fileRejections, setFileRejections] = useState2([]);
698
+ const [totalSize, setTotalSize] = useState3(0);
699
+ const [fileRejections, setFileRejections] = useState3([]);
551
700
  const client = useQueryClient();
552
701
  const formMethods = useFormContext2();
553
702
  const options = __spreadProps(__spreadValues({}, uploadOptions), {
@@ -581,10 +730,10 @@ var FileSelector = ({
581
730
  const rejections = fileRejections.filter((value) => value.id !== id);
582
731
  setFileRejections(rejections);
583
732
  };
584
- return /* @__PURE__ */ jsxs8(Fragment5, { children: [
585
- enableDropArea ? /* @__PURE__ */ jsxs8(Fragment5, { children: [
586
- label ? /* @__PURE__ */ jsx6(Typography4, { marginBottom: "4px", children: label }) : null,
587
- /* @__PURE__ */ jsx6(
733
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
734
+ enableDropArea ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
735
+ label ? /* @__PURE__ */ jsx12(Typography4, { marginBottom: "4px", children: label }) : null,
736
+ /* @__PURE__ */ jsx12(
588
737
  Dropzone,
589
738
  {
590
739
  name,
@@ -601,15 +750,15 @@ var FileSelector = ({
601
750
  validator
602
751
  }
603
752
  ),
604
- /* @__PURE__ */ jsx6(FileTypesMessage, { allowedFileTypes, maxFileSize: maxSize, variant: "caption" }),
753
+ /* @__PURE__ */ jsx12(FileTypesMessage, { allowedFileTypes, maxFileSize: maxSize, variant: "caption" }),
605
754
  children
606
- ] }) : /* @__PURE__ */ jsxs8(Grid2, { container: true, rowSpacing: 3, flexDirection: "column", children: [
607
- /* @__PURE__ */ jsxs8(Grid2, { children: [
608
- /* @__PURE__ */ jsx6(HeaderMessage, { maxFiles, maxSize }),
609
- /* @__PURE__ */ jsx6(FileTypesMessage, { allowedFileTypes, variant: "body2" })
755
+ ] }) : /* @__PURE__ */ jsxs10(Grid2, { container: true, rowSpacing: 3, flexDirection: "column", children: [
756
+ /* @__PURE__ */ jsxs10(Grid2, { children: [
757
+ /* @__PURE__ */ jsx12(HeaderMessage, { maxFiles, maxSize }),
758
+ /* @__PURE__ */ jsx12(FileTypesMessage, { allowedFileTypes, variant: "body2" })
610
759
  ] }),
611
- children ? /* @__PURE__ */ jsx6(Grid2, { children }) : null,
612
- /* @__PURE__ */ jsx6(Grid2, { children: /* @__PURE__ */ jsx6(
760
+ children ? /* @__PURE__ */ jsx12(Grid2, { children }) : null,
761
+ /* @__PURE__ */ jsx12(Grid2, { children: /* @__PURE__ */ jsx12(
613
762
  Dropzone,
614
763
  {
615
764
  name,
@@ -627,7 +776,7 @@ var FileSelector = ({
627
776
  }
628
777
  ) })
629
778
  ] }),
630
- fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */ jsx6(
779
+ fileRejections.length > 0 ? fileRejections.map((rejection) => /* @__PURE__ */ jsx12(
631
780
  ErrorAlert,
632
781
  {
633
782
  errors: rejection.errors,
@@ -637,7 +786,7 @@ var FileSelector = ({
637
786
  },
638
787
  rejection.id
639
788
  )) : null,
640
- /* @__PURE__ */ jsx6(
789
+ /* @__PURE__ */ jsx12(
641
790
  FileList,
642
791
  {
643
792
  files: files || [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@availity/mui-file-selector",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Availity MUI file-selector Component - part of the @availity/element design system",
5
5
  "keywords": [
6
6
  "react",
@@ -50,7 +50,7 @@
50
50
  "@availity/mui-list": "^1.0.1",
51
51
  "@availity/mui-progress": "^1.0.1",
52
52
  "@availity/mui-typography": "^1.0.1",
53
- "@availity/upload-core": "^7.0.1",
53
+ "@availity/upload-core": "^7.0.3",
54
54
  "@tanstack/react-query": "^4.36.1",
55
55
  "react-dropzone": "^11.7.1",
56
56
  "react-hook-form": "^7.54.2",
@@ -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 xs={12} justifyContent="end" display="flex" paddingTop={2.5}>
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
- name: 'file-selector',
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 [error, setError] = useState(false);
29
- // const [password, setPassword] = useState('');
30
- // const [modalOpen, setModalOpen] = useState(false);
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
- setError(false);
40
+ setErrorMessage('');
35
41
 
36
42
  if (onProgress) onProgress(upload);
37
43
  };
38
44
 
39
45
  const handleOnError = () => {
40
- setError(true);
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
- setError(false);
53
+ setErrorMessage('');
48
54
 
49
55
  if (onSuccess) onSuccess(upload);
50
56
  };
51
57
 
52
- // const toggleModal = () => {
53
- // setModalOpen((prev) => !prev);
54
- // setPassword('');
55
- // };
58
+ const toggleModal = () => {
59
+ setModalOpen((prev) => !prev);
60
+ setPassword('');
61
+ };
56
62
 
57
- // const verifyPassword: FormEventHandler<HTMLFormElement> = (event) => {
58
- // event.preventDefault();
59
- // event.stopPropagation();
60
- // upload.sendPassword(password);
61
- // toggleModal();
62
- // };
63
+ const verifyPassword: FormEventHandler<HTMLFormElement> = (event) => {
64
+ event.preventDefault();
65
+ event.stopPropagation();
66
+ upload.sendPassword(password);
67
+ toggleModal();
68
+ };
63
69
 
64
- // const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
65
- // setPassword(event.target.value);
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 upload.errorMessage ? (
73
- <>
74
- <ListItemText primaryTypographyProps={{ color: 'text.error', variant: 'body2' }}>
75
- <WarningTriangleIcon /> {upload.errorMessage}
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
- {/* {upload.status === 'encrypted' && (
83
+ {upload.status === 'encrypted' && (
78
84
  <div className="pwRequired">
79
- <Button color="primary" onClick={toggleModal}>
80
- Enter password
85
+ <Button color="secondary" size="small" onClick={toggleModal}>
86
+ Enter Password
81
87
  </Button>
82
- <Modal isOpen={modalOpen} toggle={toggleModal}>
88
+ <Dialog open={modalOpen} onClose={toggleModal}>
83
89
  <form onSubmit={verifyPassword}>
84
- <ModalHeader toggle={toggleModal}>Enter Password</ModalHeader>
85
- <ModalBody>
86
- <Label for="upload-password">Password</Label>
87
- <Input id="upload-password" onChange={handlePasswordChange} type="password" placeholder="password" />
88
- </ModalBody>
89
- <ModalFooter>
90
- <Button color="primary">Ok</Button>
91
- </ModalFooter>
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
- </Modal>
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
  );