@availity/mui-file-selector 1.3.1 → 1.4.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 +15 -0
- package/README.md +5 -0
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +3 -2
- package/dist/index.mjs +3 -2
- package/package.json +1 -1
- package/src/lib/FileList.tsx +10 -10
- package/src/lib/FileSelector.tsx +5 -1
- package/src/lib/bs4migration.mdx +120 -0
- package/src/lib/useUploadCore.tsx +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.4.0](https://github.com/Availity/element/compare/@availity/mui-file-selector@1.3.2...@availity/mui-file-selector@1.4.0) (2025-04-04)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **mui-file-selector:** add onProgress to useUploadCore ([6bef795](https://github.com/Availity/element/commit/6bef7950f0e392fdbf7b395f45ed16562cda0295))
|
|
11
|
+
|
|
12
|
+
## [1.3.2](https://github.com/Availity/element/compare/@availity/mui-file-selector@1.3.1...@availity/mui-file-selector@1.3.2) (2025-03-31)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **mui-file-selector:** check if upload is defined before attempting to render CustomRow ([26d22cc](https://github.com/Availity/element/commit/26d22cc44e18ac9c0fce9ea64c2d8d6c8a4cff47))
|
|
18
|
+
* **mui-file-selector:** update customFileRow type on FileSelector ([8020d04](https://github.com/Availity/element/commit/8020d045d68b744fddd21b8f4953a4fd63c551de))
|
|
19
|
+
|
|
5
20
|
## [1.3.1](https://github.com/Availity/element/compare/@availity/mui-file-selector@1.3.0...@availity/mui-file-selector@1.3.1) (2025-03-27)
|
|
6
21
|
|
|
7
22
|
### Dependency Updates
|
package/README.md
CHANGED
|
@@ -170,6 +170,10 @@ const MyFileUploadComponent = () => {
|
|
|
170
170
|
// Handle upload error - e.g., show error message, retry upload
|
|
171
171
|
};
|
|
172
172
|
|
|
173
|
+
const handleOnProgress = (error) => {
|
|
174
|
+
// Handle upload error - e.g., show error message, retry upload
|
|
175
|
+
};
|
|
176
|
+
|
|
173
177
|
return (
|
|
174
178
|
<FileSelector
|
|
175
179
|
name="documentUpload"
|
|
@@ -183,6 +187,7 @@ const MyFileUploadComponent = () => {
|
|
|
183
187
|
uploadOptions={{
|
|
184
188
|
onSuccess: handleOnSuccess,
|
|
185
189
|
onError: handleOnError,
|
|
190
|
+
onProgress: handleOnProgress,
|
|
186
191
|
}}
|
|
187
192
|
/>
|
|
188
193
|
);
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { MouseEvent, Dispatch, ChangeEvent, RefObject, ReactNode
|
|
2
|
+
import { MouseEvent, Dispatch, ChangeEvent, RefObject, ReactNode } from 'react';
|
|
3
3
|
import { DropEvent, FileRejection, FileError, DropzoneInputProps } from 'react-dropzone';
|
|
4
4
|
import Upload, { UploadOptions } from '@availity/upload-core';
|
|
5
5
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
@@ -87,6 +87,7 @@ declare const ErrorAlert: ({ errors, fileName, id, onClose }: ErrorAlertProps) =
|
|
|
87
87
|
type Options = {
|
|
88
88
|
onError?: (error: Error) => void;
|
|
89
89
|
onSuccess?: () => void;
|
|
90
|
+
onProgress?: () => void;
|
|
90
91
|
} & UploadOptions;
|
|
91
92
|
type UploadQueryOptions = UseQueryOptions<Upload, Error, Upload, [string, string, Options]>;
|
|
92
93
|
declare function useUploadCore(file: File, options: Options, queryOptions?: UploadQueryOptions): _tanstack_react_query.UseQueryResult<Upload, Error>;
|
|
@@ -205,7 +206,11 @@ type FileSelectorProps = {
|
|
|
205
206
|
/**
|
|
206
207
|
* Componet to render the File information. This should return a `ListItem`
|
|
207
208
|
*/
|
|
208
|
-
customFileRow?: ElementType<
|
|
209
|
+
customFileRow?: React.ElementType<{
|
|
210
|
+
upload?: Upload;
|
|
211
|
+
options: Options;
|
|
212
|
+
onRemoveFile: (id: string, upload: Upload) => void;
|
|
213
|
+
}>;
|
|
209
214
|
/**
|
|
210
215
|
* Whether to use the cloud upload endpoint
|
|
211
216
|
* When true, uses '/cloud/web/appl/vault/upload/v1/resumable'
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { MouseEvent, Dispatch, ChangeEvent, RefObject, ReactNode
|
|
2
|
+
import { MouseEvent, Dispatch, ChangeEvent, RefObject, ReactNode } from 'react';
|
|
3
3
|
import { DropEvent, FileRejection, FileError, DropzoneInputProps } from 'react-dropzone';
|
|
4
4
|
import Upload, { UploadOptions } from '@availity/upload-core';
|
|
5
5
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
@@ -87,6 +87,7 @@ declare const ErrorAlert: ({ errors, fileName, id, onClose }: ErrorAlertProps) =
|
|
|
87
87
|
type Options = {
|
|
88
88
|
onError?: (error: Error) => void;
|
|
89
89
|
onSuccess?: () => void;
|
|
90
|
+
onProgress?: () => void;
|
|
90
91
|
} & UploadOptions;
|
|
91
92
|
type UploadQueryOptions = UseQueryOptions<Upload, Error, Upload, [string, string, Options]>;
|
|
92
93
|
declare function useUploadCore(file: File, options: Options, queryOptions?: UploadQueryOptions): _tanstack_react_query.UseQueryResult<Upload, Error>;
|
|
@@ -205,7 +206,11 @@ type FileSelectorProps = {
|
|
|
205
206
|
/**
|
|
206
207
|
* Componet to render the File information. This should return a `ListItem`
|
|
207
208
|
*/
|
|
208
|
-
customFileRow?: ElementType<
|
|
209
|
+
customFileRow?: React.ElementType<{
|
|
210
|
+
upload?: Upload;
|
|
211
|
+
options: Options;
|
|
212
|
+
onRemoveFile: (id: string, upload: Upload) => void;
|
|
213
|
+
}>;
|
|
209
214
|
/**
|
|
210
215
|
* Whether to use the cloud upload endpoint
|
|
211
216
|
* When true, uses '/cloud/web/appl/vault/upload/v1/resumable'
|
package/dist/index.js
CHANGED
|
@@ -660,11 +660,12 @@ var import_react_query = require("@tanstack/react-query");
|
|
|
660
660
|
var import_upload_core = __toESM(require("@availity/upload-core"));
|
|
661
661
|
function startUpload(file, options) {
|
|
662
662
|
return __async(this, null, function* () {
|
|
663
|
-
const _a = options, { onSuccess, onError } = _a, uploadOptions = __objRest(_a, ["onSuccess", "onError"]);
|
|
663
|
+
const _a = options, { onSuccess, onError, onProgress } = _a, uploadOptions = __objRest(_a, ["onSuccess", "onError", "onProgress"]);
|
|
664
664
|
const upload = new import_upload_core.default(file, uploadOptions);
|
|
665
665
|
yield upload.generateId();
|
|
666
666
|
if (onSuccess) upload.onSuccess.push(onSuccess);
|
|
667
667
|
if (onError) upload.onError.push(onError);
|
|
668
|
+
if (onProgress) upload.onProgress.push(onProgress);
|
|
668
669
|
upload.start();
|
|
669
670
|
return upload;
|
|
670
671
|
});
|
|
@@ -692,8 +693,8 @@ var FileRow = ({
|
|
|
692
693
|
}) => {
|
|
693
694
|
const Icon = getFileExtIcon(file.name);
|
|
694
695
|
const { data: upload } = useUploadCore(file, options, queryOptions);
|
|
695
|
-
if (CustomRow) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CustomRow, { upload, options, onRemoveFile });
|
|
696
696
|
if (!upload) return null;
|
|
697
|
+
if (CustomRow) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(CustomRow, { upload, options, onRemoveFile });
|
|
697
698
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
698
699
|
import_mui_list3.ListItem,
|
|
699
700
|
{
|
package/dist/index.mjs
CHANGED
|
@@ -635,11 +635,12 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
635
635
|
import Upload from "@availity/upload-core";
|
|
636
636
|
function startUpload(file, options) {
|
|
637
637
|
return __async(this, null, function* () {
|
|
638
|
-
const _a = options, { onSuccess, onError } = _a, uploadOptions = __objRest(_a, ["onSuccess", "onError"]);
|
|
638
|
+
const _a = options, { onSuccess, onError, onProgress } = _a, uploadOptions = __objRest(_a, ["onSuccess", "onError", "onProgress"]);
|
|
639
639
|
const upload = new Upload(file, uploadOptions);
|
|
640
640
|
yield upload.generateId();
|
|
641
641
|
if (onSuccess) upload.onSuccess.push(onSuccess);
|
|
642
642
|
if (onError) upload.onError.push(onError);
|
|
643
|
+
if (onProgress) upload.onProgress.push(onProgress);
|
|
643
644
|
upload.start();
|
|
644
645
|
return upload;
|
|
645
646
|
});
|
|
@@ -667,8 +668,8 @@ var FileRow = ({
|
|
|
667
668
|
}) => {
|
|
668
669
|
const Icon = getFileExtIcon(file.name);
|
|
669
670
|
const { data: upload } = useUploadCore(file, options, queryOptions);
|
|
670
|
-
if (CustomRow) return /* @__PURE__ */ jsx11(CustomRow, { upload, options, onRemoveFile });
|
|
671
671
|
if (!upload) return null;
|
|
672
|
+
if (CustomRow) return /* @__PURE__ */ jsx11(CustomRow, { upload, options, onRemoveFile });
|
|
672
673
|
return /* @__PURE__ */ jsxs8(
|
|
673
674
|
ListItem2,
|
|
674
675
|
{
|
package/package.json
CHANGED
package/src/lib/FileList.tsx
CHANGED
|
@@ -53,10 +53,10 @@ export const FileRow = ({
|
|
|
53
53
|
|
|
54
54
|
const { data: upload } = useUploadCore(file, options, queryOptions);
|
|
55
55
|
|
|
56
|
-
if (CustomRow) return <CustomRow upload={upload} options={options} onRemoveFile={onRemoveFile} />;
|
|
57
|
-
|
|
58
56
|
if (!upload) return null;
|
|
59
57
|
|
|
58
|
+
if (CustomRow) return <CustomRow upload={upload} options={options} onRemoveFile={onRemoveFile} />;
|
|
59
|
+
|
|
60
60
|
return (
|
|
61
61
|
<ListItem
|
|
62
62
|
disableGutters
|
|
@@ -74,19 +74,19 @@ export const FileRow = ({
|
|
|
74
74
|
)
|
|
75
75
|
}
|
|
76
76
|
>
|
|
77
|
-
<Grid container spacing={2} alignItems="center" justifyContent="space-between" width="100%"
|
|
78
|
-
<Grid size={{ xs:
|
|
79
|
-
<ListItemIcon sx={{minWidth: '1.5rem'}}>
|
|
77
|
+
<Grid container spacing={2} alignItems="center" justifyContent="space-between" width="100%" flexWrap="wrap">
|
|
78
|
+
<Grid size={{ xs: 'auto' }}>
|
|
79
|
+
<ListItemIcon sx={{ minWidth: '1.5rem' }}>
|
|
80
80
|
<Icon />
|
|
81
81
|
</ListItemIcon>
|
|
82
82
|
</Grid>
|
|
83
|
-
<Grid size={{ xs: 4 }} sx={{minWidth: '8rem'}}>
|
|
84
|
-
<ListItemText sx={{wordBreak: 'break-all'}}>{upload.trimFileName(upload.file.name)}</ListItemText>
|
|
83
|
+
<Grid size={{ xs: 4 }} sx={{ minWidth: '8rem' }}>
|
|
84
|
+
<ListItemText sx={{ wordBreak: 'break-all' }}>{upload.trimFileName(upload.file.name)}</ListItemText>
|
|
85
85
|
</Grid>
|
|
86
|
-
<Grid size={{ xs: 2 }} sx={{minWidth: '3rem'}}>
|
|
87
|
-
<ListItemText sx={{textAlign: 'end'}}>{formatBytes(upload.file.size)}</ListItemText>
|
|
86
|
+
<Grid size={{ xs: 2 }} sx={{ minWidth: '3rem' }}>
|
|
87
|
+
<ListItemText sx={{ textAlign: 'end' }}>{formatBytes(upload.file.size)}</ListItemText>
|
|
88
88
|
</Grid>
|
|
89
|
-
<Grid size={{ xs: 'grow' }} sx={{minWidth: '6rem'}}>
|
|
89
|
+
<Grid size={{ xs: 'grow' }} sx={{ minWidth: '6rem' }}>
|
|
90
90
|
<UploadProgressBar upload={upload} />
|
|
91
91
|
</Grid>
|
|
92
92
|
</Grid>
|
package/src/lib/FileSelector.tsx
CHANGED
|
@@ -66,7 +66,11 @@ export type FileSelectorProps = {
|
|
|
66
66
|
/**
|
|
67
67
|
* Componet to render the File information. This should return a `ListItem`
|
|
68
68
|
*/
|
|
69
|
-
customFileRow?: ElementType<
|
|
69
|
+
customFileRow?: React.ElementType<{
|
|
70
|
+
upload?: Upload;
|
|
71
|
+
options: Options;
|
|
72
|
+
onRemoveFile: (id: string, upload: Upload) => void;
|
|
73
|
+
}>;
|
|
70
74
|
/**
|
|
71
75
|
* Whether to use the cloud upload endpoint
|
|
72
76
|
* When true, uses '/cloud/web/appl/vault/upload/v1/resumable'
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="BS4 Migration/Upload" />
|
|
4
|
+
|
|
5
|
+
# Upload Migration
|
|
6
|
+
|
|
7
|
+
The `Upload` component from `@availity/upload` and `@availity/form-upload` has been renamed to the `FileSelector` component. It still uses `@availity/upload-core` package to do the lifting, however, we have renamed, removed, and added some things.
|
|
8
|
+
|
|
9
|
+
For more in depth component information, visit:
|
|
10
|
+
|
|
11
|
+
- [Availity Design Documentation](https://design.availity.com/2e36e50c7/p/121639-file-selector)
|
|
12
|
+
- [Component Documentation](./?path=/docs/components-file-selector-file-selector--docs)
|
|
13
|
+
|
|
14
|
+
## Key Differences (not exhaustive list)
|
|
15
|
+
|
|
16
|
+
### Props
|
|
17
|
+
|
|
18
|
+
#### ✅ New
|
|
19
|
+
|
|
20
|
+
- `onDrop`: this prop serves as an `onChange` callback. Use it to get access to the files and the change event
|
|
21
|
+
- `disableRemove`: used to prevent removing the file from the list
|
|
22
|
+
- `validator`: allows for custom validation
|
|
23
|
+
- `customFileRow`: pass in your own component to be used in the FileList
|
|
24
|
+
- `queryOptions`: options for the `useQuery` hook
|
|
25
|
+
|
|
26
|
+
#### ⚠️ Changed
|
|
27
|
+
|
|
28
|
+
- `max` -> `maxFiles`
|
|
29
|
+
- `showFileDrop` -> `enableDropArea`
|
|
30
|
+
|
|
31
|
+
#### 🚫 Removed
|
|
32
|
+
|
|
33
|
+
- `onFileUpload`: this prop has been removed in favor of adding `onProgress`, `onSuccess`, and `onError`. Previously, you were required to add these functions yourself. Now they can be passed directly to the component
|
|
34
|
+
- `buttonText` (use children prop instead)
|
|
35
|
+
- `buttonClassName`
|
|
36
|
+
- `dropZoneText`
|
|
37
|
+
- `component`
|
|
38
|
+
|
|
39
|
+
### Form Management
|
|
40
|
+
|
|
41
|
+
- The FileSelector uses `react-hook-form` instead of `Formik`
|
|
42
|
+
- Must wrap component with FormProvider from `react-hook-form`
|
|
43
|
+
- The `react-hook-form` provider maintains the state of the selected files. It does not use `@availity/upload-core`.
|
|
44
|
+
|
|
45
|
+
## Code Examples
|
|
46
|
+
|
|
47
|
+
`availity-react` Example:
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import { Upload } from '@availity/form-upload';
|
|
51
|
+
import { Form } from '@availity/form';
|
|
52
|
+
|
|
53
|
+
const UploadForm = () => (
|
|
54
|
+
<Form initialValues={{ fileUpload: [] }} onSubmit={(values) => console.log(values)}>
|
|
55
|
+
<Upload
|
|
56
|
+
name="fileUpload"
|
|
57
|
+
clientId="my-client-id"
|
|
58
|
+
bucketId="my-bucket-id"
|
|
59
|
+
customerId="my-customer-id"
|
|
60
|
+
maxSize={5 * 1024 * 1024}
|
|
61
|
+
multiple={true}
|
|
62
|
+
allowedFileTypes={['.pdf', '.doc', '.docx']}
|
|
63
|
+
/>
|
|
64
|
+
</Form>
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`@availity/element` Example:
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { FileSelector } from '@availity/mui-file-selector';
|
|
72
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
73
|
+
|
|
74
|
+
const UploadForm = () => {
|
|
75
|
+
const methods = useForm({
|
|
76
|
+
defaultValues: {
|
|
77
|
+
fileUpload: [],
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const onSubmit = (data) => console.log(data);
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<FormProvider {...methods}>
|
|
85
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
86
|
+
<FileSelector
|
|
87
|
+
name="fileUpload"
|
|
88
|
+
clientId="my-client-id"
|
|
89
|
+
bucketId="my-bucket-id"
|
|
90
|
+
customerId="my-customer-id"
|
|
91
|
+
maxSize={5 * 1024 * 1024}
|
|
92
|
+
maxFiles={5}
|
|
93
|
+
multiple={true}
|
|
94
|
+
allowedFileTypes={['.pdf', '.doc', '.docx']}
|
|
95
|
+
/>
|
|
96
|
+
</form>
|
|
97
|
+
</FormProvider>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Additional Considerations
|
|
103
|
+
|
|
104
|
+
### Error Handling
|
|
105
|
+
|
|
106
|
+
- The new component provides more detailed error feedback
|
|
107
|
+
- Errors are displayed using Element Alert components
|
|
108
|
+
- Custom error handling can be implemented through the validator prop
|
|
109
|
+
|
|
110
|
+
### File List Display
|
|
111
|
+
|
|
112
|
+
- Files are now displayed in a MUI List component
|
|
113
|
+
- Can be customized using the customFileRow prop
|
|
114
|
+
- Shows upload progress and status more clearly
|
|
115
|
+
|
|
116
|
+
### Accessibility
|
|
117
|
+
|
|
118
|
+
- Improved keyboard navigation
|
|
119
|
+
- Better screen reader support
|
|
120
|
+
- Clear focus indicators
|
|
@@ -6,18 +6,20 @@ import type { UploadOptions } from '@availity/upload-core';
|
|
|
6
6
|
export type Options = {
|
|
7
7
|
onError?: (error: Error) => void;
|
|
8
8
|
onSuccess?: () => void;
|
|
9
|
+
onProgress?: () => void;
|
|
9
10
|
} & UploadOptions;
|
|
10
11
|
|
|
11
12
|
export type UploadQueryOptions = UseQueryOptions<Upload, Error, Upload, [string, string, Options]>;
|
|
12
13
|
|
|
13
14
|
async function startUpload(file: File, options: Options) {
|
|
14
|
-
const { onSuccess, onError, ...uploadOptions } = options;
|
|
15
|
+
const { onSuccess, onError, onProgress, ...uploadOptions } = options;
|
|
15
16
|
const upload = new Upload(file, uploadOptions);
|
|
16
17
|
|
|
17
18
|
await upload.generateId();
|
|
18
19
|
|
|
19
20
|
if (onSuccess) upload.onSuccess.push(onSuccess);
|
|
20
21
|
if (onError) upload.onError.push(onError);
|
|
22
|
+
if (onProgress) upload.onProgress.push(onProgress);
|
|
21
23
|
|
|
22
24
|
upload.start();
|
|
23
25
|
|