{"version":3,"file":"UploadButton.mjs","sources":["../../../src/uploadInput/uploadButton/UploadButton.tsx"],"sourcesContent":["import { PlusCircle as PlusIcon, Upload as UploadIcon } from '@transferwise/icons';\nimport { clsx } from 'clsx';\nimport {\n  ChangeEvent,\n  DragEvent,\n  useRef,\n  useState,\n  forwardRef,\n  useImperativeHandle,\n  ForwardedRef,\n} from 'react';\nimport { useIntl } from 'react-intl';\n\nimport Body from '../../body';\nimport { FileType, Typography } from '../../common';\n\nimport MESSAGES from './UploadButton.messages';\nimport { DEFAULT_SIZE_LIMIT, imageFileTypes } from './defaults';\nimport getAllowedFileTypes from './getAllowedFileTypes';\n\ntype AllowedFileTypes = string | readonly string[] | readonly FileType[];\nexport type UploadButtonProps = {\n  /**\n   * Disable the upload button if your app is not yet ready to accept uploads\n   */\n  disabled?: boolean;\n\n  /**\n   * Should be true, if the UploadInput has at least 1\n   * file (valid or invalid) listed.\n   */\n  withEntries?: boolean;\n\n  /**\n   * Allow multiple file uploads\n   */\n  multiple?: boolean;\n\n  /**\n   * List of allowed filetypes, eg. '*' | '.zip,application/zip' | ['.jpg,.jpeg,image/jpeg', '.png,image/png'] (default: image files + PDF)\n   */\n  fileTypes?: AllowedFileTypes;\n\n  /**\n   * Size limit in KBs (1000 KB = 1 MB).\n   * If set to `null`, no size limit will be applied.\n   * @default 5000\n   */\n  sizeLimit?: number | null;\n\n  /**\n   * Description for the upload button\n   */\n  description?: string | undefined;\n\n  /**\n   * Maximum number of files allowed, if provided, shows error below file item\n   */\n  maxFiles?: number;\n\n  /**\n   * Called when some files were successfully selected\n   *\n   * @param files\n   */\n  onChange: (files: FileList) => void;\n\n  /**\n   * Id for the upload input\n   */\n  id?: string;\n\n  /**\n   * Title for the upload button\n   */\n  uploadButtonTitle?: string;\n};\n\nexport enum TEST_IDS {\n  uploadInput = 'uploadInput',\n  mediaBody = 'mediaBody',\n}\n\nconst onDragOver = (event: DragEvent): void => {\n  event.preventDefault();\n};\n\nconst DEFAULT_FILE_INPUT_ID = 'np-upload-button';\nconst UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(\n  (\n    {\n      disabled,\n      withEntries,\n      multiple,\n      description,\n      fileTypes = imageFileTypes,\n      sizeLimit = DEFAULT_SIZE_LIMIT,\n      maxFiles,\n      onChange,\n      id = DEFAULT_FILE_INPUT_ID,\n      uploadButtonTitle,\n    },\n    ref: ForwardedRef<HTMLInputElement | null>,\n  ) => {\n    const { formatMessage } = useIntl();\n    const inputRef = useRef<HTMLInputElement | null>(null);\n\n    useImperativeHandle(ref, () => {\n      if (!inputRef.current) {\n        throw new Error('inputRef.current is null');\n      }\n      return inputRef.current;\n    }, []);\n\n    const [isDropping, setIsDropping] = useState(false);\n\n    const dragCounter = useRef(0);\n\n    const reset = (): void => {\n      dragCounter.current = 0;\n      setIsDropping(false);\n    };\n\n    const onDragLeave = (event: DragEvent): void => {\n      event.preventDefault();\n      dragCounter.current -= 1;\n      if (dragCounter.current === 0) {\n        setIsDropping(false);\n      }\n    };\n\n    const onDragEnter = (event: DragEvent): void => {\n      event.preventDefault();\n      dragCounter.current += 1;\n      if (dragCounter.current === 1) {\n        setIsDropping(true);\n      }\n    };\n\n    const onDrop = (event: DragEvent): void => {\n      event.preventDefault();\n      reset();\n      if (event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {\n        onChange(event.dataTransfer.files);\n      }\n    };\n\n    const filesSelected = (event: ChangeEvent<HTMLInputElement>): void => {\n      const { files } = event.target;\n\n      if (files) {\n        onChange(files);\n\n        if (inputRef.current) {\n          inputRef.current.value = '';\n        }\n      }\n    };\n\n    const getFileTypesDescription = (): string => {\n      if (fileTypes === '*') {\n        return fileTypes;\n      }\n\n      return getAllowedFileTypes(Array.isArray(fileTypes) ? fileTypes : [fileTypes]).join(', ');\n    };\n\n    function getDescription() {\n      if (description) {\n        return description;\n      }\n\n      const fileTypesDescription = getFileTypesDescription();\n\n      const derivedFileDescription =\n        fileTypesDescription === '*' ? formatMessage(MESSAGES.allFileTypes) : fileTypesDescription;\n\n      if (typeof sizeLimit === 'number') {\n        return formatMessage(MESSAGES.instructions, {\n          fileTypes: derivedFileDescription,\n          size: Math.round(sizeLimit / 1000),\n        });\n      }\n\n      return derivedFileDescription;\n    }\n\n    function getAcceptedTypes(): Pick<React.ComponentPropsWithoutRef<'input'>, 'accept'> {\n      const areAllFilesAllowed = getFileTypesDescription() === '*';\n\n      if (areAllFilesAllowed) {\n        return {}; // file input by default allows all files\n      }\n\n      if (Array.isArray(fileTypes)) {\n        return { accept: fileTypes.join(',') };\n      }\n\n      return { accept: fileTypes as string };\n    }\n\n    function renderDescription() {\n      return (\n        <Body className=\"np-upload-input__text\">\n          {getDescription()}\n          {maxFiles && (\n            <>\n              <br />\n              {formatMessage(MESSAGES.maximumFiles, { maxFiles })}\n            </>\n          )}\n        </Body>\n      );\n    }\n\n    function renderButtonTitle() {\n      if (uploadButtonTitle) {\n        return uploadButtonTitle;\n      }\n      return formatMessage(multiple ? MESSAGES.uploadFiles : MESSAGES.uploadFile);\n    }\n\n    return (\n      <label\n        className={clsx(\n          'np-upload-input__upload-button',\n          `np-upload-input__upload-button--${disabled ? 'disabled' : 'enabled'}`,\n          `np-upload-input__upload-button--${withEntries ? 'with-entries' : 'without-entries'}`,\n          {\n            'is-dropping': isDropping,\n          },\n        )}\n        htmlFor={id}\n        {...(!disabled && { onDragEnter, onDragLeave, onDrop, onDragOver })}\n      >\n        <span className=\"np-upload-input__icon\">\n          <UploadIcon size={24} className=\"text-link\" />\n        </span>\n        <div className=\"np-upload-input__item-content\" data-testid={TEST_IDS.mediaBody}>\n          <Body type={Typography.BODY_LARGE_BOLD} className=\"np-upload-input__title\">\n            {renderButtonTitle()}\n          </Body>\n          {renderDescription()}\n        </div>\n        <input\n          className=\"np-upload-input__upload-button-input sr-only\"\n          type=\"file\"\n          id={id}\n          {...getAcceptedTypes()}\n          {...(multiple && { multiple: true })}\n          ref={inputRef}\n          disabled={disabled}\n          name=\"file-upload\"\n          data-testid={TEST_IDS.uploadInput}\n          onChange={filesSelected}\n        />\n        {isDropping && (\n          <div\n            className={clsx(\n              'np-upload-input__drop-file-overlay',\n              'droppable-card',\n              'droppable-dropping-card',\n              'droppable-card-content',\n            )}\n          >\n            <PlusIcon className=\"m-x-1\" size={24} />\n            <div>{formatMessage(MESSAGES.dropFile)}</div>\n          </div>\n        )}\n      </label>\n    );\n  },\n);\n\nUploadButton.displayName = 'UploadButton';\n\nexport default UploadButton;\n"],"names":["TEST_IDS","onDragOver","event","preventDefault","DEFAULT_FILE_INPUT_ID","UploadButton","forwardRef","disabled","withEntries","multiple","description","fileTypes","imageFileTypes","sizeLimit","DEFAULT_SIZE_LIMIT","maxFiles","onChange","id","uploadButtonTitle","ref","formatMessage","useIntl","inputRef","useRef","useImperativeHandle","current","Error","isDropping","setIsDropping","useState","dragCounter","reset","onDragLeave","onDragEnter","onDrop","dataTransfer","files","filesSelected","target","value","getFileTypesDescription","getAllowedFileTypes","Array","isArray","join","getDescription","fileTypesDescription","derivedFileDescription","MESSAGES","allFileTypes","instructions","size","Math","round","getAcceptedTypes","areAllFilesAllowed","accept","renderDescription","_jsxs","Body","className","children","_Fragment","_jsx","maximumFiles","renderButtonTitle","uploadFiles","uploadFile","clsx","htmlFor","UploadIcon","mediaBody","type","Typography","BODY_LARGE_BOLD","name","uploadInput","PlusIcon","dropFile","displayName"],"mappings":"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"}