jobiqo-cl
Version:
[](https://circleci.com/gh/jobiqo/jobiqo-cl)
145 lines (142 loc) • 8.1 kB
JavaScript
import React__default, { Component } from 'react';
import { Button } from '../01-button/index.js';
import { FormLabel } from '../11-form-item/01-form-label/index.js';
import { FormDescription } from '../11-form-item/02-form-description/index.js';
import InlineError from '../09-inline-error/index.js';
import FlexItems from '../../06-layout/03-flex/index.js';
import FlexItem from '../../06-layout/03-flex/02-flex-item/index.js';
import Spacing from '../../06-layout/07-spacing/index.js';
import Text from '../../13-text/03-text/index.js';
import CloseIcon from '../../../../icons/Close.js';
import DownloadIcon from '../../../../icons/Download.js';
import InfoIcon from '../../../../icons/Info.js';
import { JobPerFileIcon } from '../../../../icons/JobPerFile.js';
import { Wrapper, FileWidgetInput, BoxFilePreviewWrapper, RemoveFileButton, FilePreviewWrapper, ImagePreviewWrapper, Preview, PreviewInfo, ImagePreviewInfoLabel, PreviewIcon } from './styles.js';
/**
* @file index.tsx
*
* @fileoverview File input component. Renders a button input together with its label.
*/
/**
* A file input is a form element where users can chose a file from their local
* computer and use it to upload.
*/
class FileInput extends Component {
constructor(props) {
super(props);
this.state = {
files: [],
errors: []
};
/**
* Triggers a click on the input.
*/
this.handleClick = event => {
this.fileInput.current.click();
};
/**
* Handle change on the input field.
*/
this.handleChange = event => {
const fileItems = [...event.target.files];
const { maxSizeMessage = 'File is too large' } = this.props;
this.setState({
errors: fileItems
.filter(f => {
return (this.props.maxSize && f.size > this.props.maxSize * 1024 * 1024);
})
.map(fileItem => {
return `${fileItem.name} : ${maxSizeMessage}`;
}),
files: fileItems
.filter(f => {
return (!this.props.maxSize ||
(this.props.maxSize && f.size <= this.props.maxSize * 1024 * 1024));
})
.map(fileItem => {
return {
file: fileItem.type.substring(0, 5) === 'image'
? URL.createObjectURL(fileItem)
: null,
filename: fileItem.name,
fileSize: fileItem.size,
type: fileItem.type
};
})
}, () => {
if (this.props.multiple) {
this.props.onChange(fileItems);
}
else {
this.props.onChange(fileItems[0]);
}
});
};
/**
* Handle change on the input field.
*/
this.removeFile = fileIndex => {
this.setState({
files: this.state.files
.filter((f, index) => index !== fileIndex)
.map(fileItem => {
return {
file: fileItem.file,
filename: fileItem.filename,
fileSize: fileItem.fileSize,
type: fileItem.type
};
})
}, () => {
if (this.props.multiple) {
this.props.onChange(this.state.files);
}
else {
this.props.onChange(this.state.files[0]);
}
});
};
// create a ref to store the textInput DOM element
this.fileInput = React__default.createRef();
}
render() {
const { label = 'File', placeholder = 'Choose file', id, description, fileTypes, error = false, required = false, multiple = false, buttonStyle = 'default', onClick } = this.props;
return (React__default.createElement(React__default.Fragment, null,
label && multiple && (React__default.createElement(React__default.Fragment, null,
React__default.createElement(FormLabel, { error: error, required: required, htmlFor: id }, label),
React__default.createElement(Spacing, null))),
React__default.createElement(Wrapper, { multiple: multiple },
multiple && (React__default.createElement(React__default.Fragment, null,
React__default.createElement(DownloadIcon, { height: "100px", width: "100px", color: "gray2", title: "Upload" }),
React__default.createElement(Spacing, null))),
React__default.createElement(React__default.Fragment, null,
label && !multiple && (React__default.createElement(FormLabel, { error: error, required: required, htmlFor: id }, label)),
description && multiple && (React__default.createElement(Text, { tag: "p", color: "gray3", textAlign: "center" }, description)),
React__default.createElement(Spacing, null),
React__default.createElement(FileWidgetInput, Object.assign({ ref: this.fileInput, onChange: this.handleChange, type: "file" }, (fileTypes ? { accept: fileTypes.join(', ') } : null), { id: id, name: id, onClick: onClick, multiple: multiple })),
React__default.createElement(Button, { onClick: this.handleClick, "data-testid": "trigger", buttonStyle: buttonStyle, type: "button" }, placeholder),
description && !multiple && (React__default.createElement(FormDescription, null, description)),
React__default.createElement(FlexItems, { flexWrap: "wrap", alignItems: "center" }, this.state.files.map((fileUploaded, index) => (React__default.createElement(FlexItem, { margin: 4, key: index },
React__default.createElement(BoxFilePreviewWrapper, null,
React__default.createElement(RemoveFileButton, null,
React__default.createElement("button", { onClick: e => this.removeFile(index) },
React__default.createElement(CloseIcon, { title: "Remove file" }))),
React__default.createElement(FilePreviewWrapper, null,
React__default.createElement(ImagePreviewWrapper, null, fileUploaded.file ? (React__default.createElement(Preview, { src: fileUploaded.file })) : (React__default.createElement(JobPerFileIcon, { title: "Attachment" }))),
React__default.createElement(PreviewInfo, null,
React__default.createElement("div", null,
React__default.createElement(ImagePreviewInfoLabel, null,
React__default.createElement(PreviewIcon, { name: "weight", title: label })),
fileUploaded.fileSize,
" KB")))))))),
this.state.errors &&
this.state.errors.map(errorMessage => (React__default.createElement("div", null,
React__default.createElement(Spacing, null),
React__default.createElement(FlexItems, { alignItems: "center" },
React__default.createElement(FlexItem, { marginRight: 4 },
React__default.createElement(InfoIcon, { title: "error", color: "danger" }),
' '),
React__default.createElement(InlineError, { message: errorMessage })))))))));
}
}
export { FileInput };