@availity/mui-file-selector
TypeScript icon, indicating that this package has built-in type declarations

1.8.1 • Public • Published

@availity/mui-file-selector

Availity MUI File Selector component to be used with @availity/element design system.

Version NPM Downloads Dependency Status

Documentation

This package extends the MUI File Selector component: MUI File Selector Docs

Live demo and documentation in our Storybook

Availity standards for design and usage can be found in the Availity Design Guide

Installation

Import Through @availity/element (Recommended)

NPM

npm install @availity/element

Yarn

yarn add @availity/element

Direct Import

NPM

This package has a few peer dependencies. Add @mui/material & @emotion/react to your project if not already installed.

npm install @availity/mui-file-selector

Yarn

yarn add @availity/mui-file-selector

File Selector vs File Selector 2

<FileSelector /> and <FileSelector2 /> are two takes on the same functionality. At a high level, the difference between the two is the logic for handling the upload request. The <FileSelector /> component utilizes @tanstack/react-query to handle the upload request logic, while <FileSelector2 /> uses the form state to handle the upload request logic.

Which component should I use?

<FileSelector /> is a more established and battle-tested component. If you don't need access to the Upload object, <FileSelector /> may be a good option for you.

<FileSelector2 /> is slightly more experimental. It maintains feature parity with <FileSelector />, but can be considered a work in progress. <FileSelector2 /> more closely aligns with our future plans for the <FileSelector /> component.

Future Plans

In a future major release of @availity/element, we will consolidate to a single File Selector component. You can think of <FileSelector2 /> as a bridge to get there. If you want to continue using the existing <FileSelector />, we will provide a simple migration path when the consolidation happens.

File Selector 2 Benefits

  • Easier access to the Upload object
  • Simplified internals
  • Aligns with future development plans

File Selector Usage

Import through @availity/element

import { FileSelector } from '@availity/element';

Direct import

import { FileSelector } from '@availity/mui-file-selector';

Basic Example

The FileSelector component must be used inside a FormProvider from react-hook-form and a QueryClientProvider from @tanstack/react-query. Each provider has its own state that is necessary for using the component. The FormProvider stores the Files that are selected while the QueryClientProvider has the upload response data.

import React from 'react';
import { FileSelector } from '@availity/mui-file-selector';

const MyComponent = () => {
  const methods = useForm({
    defaultValues: {
      myFiles: [] as File[],
    },
  });

  const client = useQueryClient();

  const files = methods.watch(props.name);

  const handleOnSubmit = (values: Record<string, File[]>) => {
    if (values.myFiles.length === 0) return;

    const queries = client.getQueriesData<Upload>(['upload']);
    const uploads = [];
    for (const [, data] of queries) {
      if (data) uploads.push(data);
    }
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(handleOnSubmit)}>
        <FileSelector
          name="myFiles"
          bucketId="your-bucket-id"
          customerId="your-customer-id"
          clientId="your-client-id"
          maxSize={5 * 1024 * 1024} // 5MB
          maxFiles={3}
          allowedFileTypes={['.pdf', '.doc', '.docx']}
        />
      </form>
    </FormProvider>
  );
};

export default MyComponent;

Advanced Examples

Note: the following examples assume you have setup react-hook-form and react-query already

File Selection Events
import React from 'react';
import { FileSelector } from '@availity/mui-file-selector';

const MyFileUploadComponent = () => {
  const handleOnDrop = (acceptedFiles, fileRejections, event) => {
    // Use this callback for interacting with the files before they are uploaded
  };

  const handleValidation = (file) => {
    // Custom validation can be added with the `validator` prop.
    // If an error fails validation here it should show up
    // in the `fileRejections` array from `onDrop`.
    //
    // To return a custom error, return an object with a code
    // and message.
    // return { code: 'an-error', message: 'An error occurred' };
  };

  return (
    <FileSelector
      name="documentUpload"
      bucketId="your-bucket-id"
      customerId="your-customer-id"
      clientId="your-client-id"
      maxSize={10 * 1024 * 1024} // 10MB
      allowedFileTypes={['.pdf', '.doc', '.docx']}
      multiple={true}
      maxFiles={5}
      onDrop={handleOnDrop}
      validator={handleValidation}
    />
  );
};

export default MyFileUploadComponent;
Upload Callbacks

It is possible to pass callbacks based on whether the upload finished successfully or there was an error.

import React from 'react';
import { FileSelector } from '@availity/mui-file-selector';

const MyFileUploadComponent = () => {
  const handleOnSuccess = () => {
    // Handle successful upload - e.g., show success message, update UI
  };

  const handleOnError = (error) => {
    // Handle upload error - e.g., show error message, retry upload
  };

  const handleOnProgress = (error) => {
    // Handle upload error - e.g., show error message, retry upload
  };

  return (
    <FileSelector
      name="documentUpload"
      bucketId="your-bucket-id"
      customerId="your-customer-id"
      clientId="your-client-id"
      maxSize={10 * 1024 * 1024} // 10MB
      allowedFileTypes={['.pdf', '.doc', '.docx']}
      multiple={true}
      maxFiles={5}
      uploadOptions={{
        onSuccess: handleOnSuccess,
        onError: handleOnError,
        onProgress: handleOnProgress,
      }}
    />
  );
};

export default MyFileUploadComponent;
Custom File Row

If you would like to show different information in each row then you are able to pass a custom FileRow component. We recommend using the ListItem component. The upload object from @availity/upload-core, the options passed to its constructor, and the onRemoveFile function will all be passed as props.

import React from 'react';
import { FileSelector } from '@availity/mui-file-selector';
import { ListItem } from '@availity/mui-list';

const FileRow = ({ upload, options, onRemoveFile }) => {
  return <ListItem>Your code here</ListItem>;
};

const MyFileUploadComponent = () => {
  return (
    <FileSelector
      name="documentUpload"
      bucketId="your-bucket-id"
      customerId="your-customer-id"
      clientId="your-client-id"
      maxSize={10 * 1024 * 1024} // 10MB
      allowedFileTypes={['.pdf', '.doc', '.docx']}
      multiple={true}
      maxFiles={5}
      customFileRow={FileRow}
    />
  );
};

export default MyFileUploadComponent;
Custom helpText

To provide custom help text, pass it as a child of the <FileSelector /> component. The help text should be formatted using the <Typography /> component with the 'caption' variant.

import React from 'react';
import { FileSelector } from '@availity/mui-file-selector';
import { Typography } from '@availity/mui-typography';

const MyComponent = () => {
  const methods = useForm({
    defaultValues: {
      myFiles: [] as File[],
    },
  });

  const client = useQueryClient();

  const files = methods.watch('myFiles);

  const handleOnSubmit = (values: Record<string, File[]>) => {
    if (values.myFiles.length === 0) return;

    const queries = client.getQueriesData<Upload>(['upload']);
    const uploads = [];
    for (const [, data] of queries) {
      if (data) uploads.push(data);
    }
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(handleOnSubmit)}>
        <FileSelector
          name="myFiles"
          bucketId="your-bucket-id"
          customerId="your-customer-id"
          clientId="your-client-id"
          maxSize={5 * 1024 * 1024} // 5MB
          maxFiles={3}
          allowedFileTypes={['.pdf', '.doc', '.docx']}
        >
          <Typography component="div" variant="caption">Here is some help text.</Typography>
        </FileSelector>
      </form>
    </FormProvider>
  );
};

export default MyComponent;

File Selector 2 Usage

Import through @availity/element

import { FileSelector2 } from '@availity/element';

Direct import

import { FileSelector2 } from '@availity/mui-file-selector';

Basic Example

The FileSelector2 component must be used inside a FormProvider from react-hook-form. Each provider has its own state that is necessary for using the component.

import React from 'react';
import { FileSelector2 } from '@availity/mui-file-selector';

const MyComponent = () => {
  const methods = useForm({
    defaultValues: {
      myFiles: [] as File[],
    },
  });

  const uploads = methods.watch(props.name);

  const handleOnSubmit = (values: Record<string, File[]>) => {
    if (values.myFiles.length === 0) return;
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(handleOnSubmit)}>
        <FileSelector2
          name="myFiles"
          bucketId="your-bucket-id"
          customerId="your-customer-id"
          clientId="your-client-id"
          maxSize={5 * 1024 * 1024} // 5MB
          maxFiles={3}
          allowedFileTypes={['.pdf', '.doc', '.docx']}
        />
      </form>
    </FormProvider>
  );
};

export default MyComponent;

Package Sidebar

Install

npm i @availity/mui-file-selector

Weekly Downloads

86

Version

1.8.1

License

MIT

Unpacked Size

287 kB

Total Files

42

Last publish

Collaborators

  • availity-cicd-bot
  • azeigler
  • cbaker1
  • chrishavekost
  • dnoler
  • dznjudo
  • gregmartdotin
  • hnicbaker
  • jordan-a-young
  • jselden
  • lauroxx
  • twarner