function FileUploader()

in src/file-uploader/file-uploader.tsx [38:237]


function FileUploader(props: FileUploaderProps) {
  const { overrides = {} } = props;
  const [, theme] = useStyletron();

  const [Root, rootProps] = getOverrides(overrides.Root, StyledRoot);
  const [FileDragAndDrop, fileDragAndDropProps] = getOverrides(
    overrides.FileDragAndDrop,
    StyledFileDragAndDrop
  );
  const [ContentMessage, contentMessageProps] = getOverrides(
    overrides.ContentMessage,
    StyledContentMessage
  );

  const [ContentSeparator, contentSeparatorProps] = getOverrides(
    overrides.ContentSeparator,
    StyledContentSeparator
  );
  const [ErrorMessage, errorMessageProps] = getOverrides(
    overrides.ErrorMessage,
    StyledErrorMessage
  );
  const [HiddenInput, hiddenInputProps] = getOverrides(overrides.HiddenInput, StyledHiddenInput);
  const [ButtonComponent, buttonProps] = getOverrides(overrides.ButtonComponent, Button);

  const [RetryButtonComponent, retryButtonProps] = getOverrides(
    overrides.RetryButtonComponent,
    Button
  );
  const [CancelButtonComponent, cancelButtonProps] = getOverrides(
    overrides.CancelButtonComponent,
    Button
  );

  const [SpinnerComponent, spinnerProps] = getOverrides(overrides.Spinner, Spinner);
  const [ProgressBarComponent, progressBarProps] = getOverrides(overrides.ProgressBar, ProgressBar);

  const afterFileDrop = !!(props.progressAmount || props.progressMessage || props.errorMessage);

  let accept;
  if (Array.isArray(props.accept)) {
    accept = props.accept.join(',');
  } else if (typeof props.accept === 'string') {
    accept = props.accept;
  }

  return (
    <Dropzone {...props} accept={accept} disabled={props.disabled || afterFileDrop}>
      {(renderProps) => {
        const { getRootProps, getInputProps, open, ...styleProps } = renderProps;

        const prefixedStyledProps = prependStyleProps({
          ...styleProps,
          isDisabled: props.disabled,
          afterFileDrop,
        });

        const getRootPropsArgs: {
          onClick?: (a: SyntheticEvent<HTMLElement>) => void;
          tabIndex: number;
        } = {
          ...(props.disableClick ? { onClick: (evt) => evt.preventDefault() } : {}),
          tabIndex: -1,
        };

        return (
          <LocaleContext.Consumer>
            {(locale) => (
              <Root data-baseweb="file-uploader" {...prefixedStyledProps} {...rootProps}>
                <FileDragAndDrop
                  {...getRootProps(getRootPropsArgs)}
                  {...prefixedStyledProps}
                  {...fileDragAndDropProps}
                >
                  {!afterFileDrop && (
                    <React.Fragment>
                      <ContentMessage {...prefixedStyledProps} {...contentMessageProps}>
                        {locale.fileuploader.dropFilesToUpload}
                      </ContentMessage>
                      {/* TODO(v11): ContentSeparator potentially can be removed in the next major version */}

                      <ContentSeparator {...prefixedStyledProps} {...contentSeparatorProps}>
                        {locale.fileuploader.or}
                      </ContentSeparator>

                      <ButtonComponent
                        disabled={props.disabled}
                        kind={KIND.secondary}
                        shape={SHAPE.pill}
                        size={BUTTON_SIZE.compact}
                        onClick={open}
                        role="button"
                        overrides={{
                          BaseButton: {
                            // @ts-ignore
                            style: ({ $theme }) => ({
                              marginTop: $theme.sizing.scale500,
                            }),
                          },
                        }}
                        {...prefixedStyledProps}
                        {...buttonProps}
                      >
                        {locale.fileuploader.browseFiles}
                      </ButtonComponent>
                    </React.Fragment>
                  )}

                  {afterFileDrop && (
                    <React.Fragment>
                      {/**
                       * Below checks typeof value to ensure if progressAmount = 0 we will
                       * render the progress bar rather than the spinner. Providing a number
                       * value implies that we expect to have some progress percent in the
                       * future. We do not want to flash the spinner in this case.
                       */}
                      {typeof props.progressAmount === 'number' ? (
                        <ProgressBarComponent
                          value={props.progressAmount}
                          overrides={{
                            BarProgress: {
                              // @ts-ignore
                              style: ({ $theme }) => ({
                                backgroundColor: props.errorMessage
                                  ? $theme.colors.negative
                                  : $theme.colors.accent,
                              }),
                            },
                          }}
                          {...progressBarProps}
                        />
                      ) : props.errorMessage ? null : (
                        <SpinnerComponent
                          $size={SPINNER_SIZE.medium}
                          $style={{ marginBottom: theme.sizing.scale300 }}
                          {...spinnerProps}
                        />
                      )}
                      {(props.errorMessage || props.progressMessage) && props.errorMessage ? (
                        <ErrorMessage {...prefixedStyledProps} {...errorMessageProps}>
                          {props.errorMessage}
                        </ErrorMessage>
                      ) : (
                        <ContentMessage {...prefixedStyledProps} {...contentMessageProps}>
                          {props.progressMessage}
                        </ContentMessage>
                      )}
                      {props.errorMessage ? (
                        <RetryButtonComponent
                          kind={KIND.tertiary}
                          onClick={() => {
                            props.onRetry && props.onRetry();
                          }}
                          aria-invalid={Boolean(props.errorMessage)}
                          aria-describedby={props['aria-describedby']}
                          aria-errormessage={props.errorMessage}
                          {...retryButtonProps}
                        >
                          {locale.fileuploader.retry}
                        </RetryButtonComponent>
                      ) : (
                        <CancelButtonComponent
                          kind={KIND.tertiary}
                          onClick={() => {
                            props.onCancel && props.onCancel();
                          }}
                          aria-describedby={props['aria-describedby']}
                          overrides={{
                            BaseButton: {
                              // @ts-ignore
                              style: ({ $theme }) => ({
                                color: $theme.colors.contentNegative,
                              }),
                            },
                          }}
                          {...cancelButtonProps}
                        >
                          {locale.fileuploader.cancel}
                        </CancelButtonComponent>
                      )}
                    </React.Fragment>
                  )}
                </FileDragAndDrop>

                <HiddenInput
                  aria-invalid={Boolean(props.errorMessage) || null}
                  aria-describedby={props['aria-describedby']}
                  aria-errormessage={props.errorMessage || null}
                  {...getInputProps()}
                  {...prefixedStyledProps}
                  {...hiddenInputProps}
                />
              </Root>
            )}
          </LocaleContext.Consumer>
        );
      }}
    </Dropzone>
  );
}