-
Notifications
You must be signed in to change notification settings - Fork 1
/
FilePicker.tsx
90 lines (77 loc) · 2.41 KB
/
FilePicker.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { observer } from 'mobx-react';
import {
FormComponent,
FormComponentProps,
observePropsState,
} from 'mobx-react-helper';
import { ChangeEvent, MouseEvent } from 'react';
import { CloseButton } from 'react-bootstrap';
import { FilePreview } from './FilePreview';
export interface FilePickerProps extends FormComponentProps {
onChange?: (value: FormComponentProps['value'], file?: File) => any;
}
@observer
@observePropsState
export class FilePicker extends FormComponent<FilePickerProps> {
static readonly displayName = 'FilePicker';
handleAdd = (event: ChangeEvent<HTMLInputElement>) => {
const file = (event.currentTarget as HTMLInputElement).files?.[0];
this.innerValue = file ? URL.createObjectURL(file) : '';
this.props.onChange?.(this.innerValue, file);
};
handleClear = (event: MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
if (this.innerValue) {
URL.revokeObjectURL(this.innerValue + '');
this.innerValue = '';
}
this.props.onChange?.(this.innerValue);
};
renderInput() {
const { id, name, value, required, disabled, accept } = this.props;
return (
<>
<input
ref={this.ref}
className="position-absolute start-0 top-0 w-100 h-100 opacity-0"
type="file"
name={value ? undefined : name}
required={!value && required}
{...{ id, disabled, accept }}
onChange={this.handleAdd}
/>
{value && <input type="hidden" name={name} value={value} />}
</>
);
}
render() {
const { value } = this,
{ className = '', style, accept } = this.props;
return (
<div
className={`form-control position-relative ${className}`}
style={style}
>
{value ? (
<FilePreview
className="w-100 h-100 object-fit-contain"
type={accept}
path={value + ''}
/>
) : (
<div className="w-100 h-100 d-flex justify-content-center align-items-center display-1">
+
</div>
)}
{this.renderInput()}
{value && (
<CloseButton
className="position-absolute top-0 end-0"
style={{ width: '0.5rem', height: '0.5rem' }}
onClick={this.handleClear}
/>
)}
</div>
);
}
}