Skip to content

Commit 402c0f4

Browse files
committed
feat(core): drag & drop
1 parent a6469b7 commit 402c0f4

File tree

5 files changed

+115
-8
lines changed

5 files changed

+115
-8
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
}
9494
},
9595
"lint-staged": {
96-
"{stories,src}/**/*.css": "stylelint --syntax css",
96+
"{stories,src}/**/*.css": "stylelint",
9797
"{stories,src}/**/*.{ts,tsx}": [
9898
"tslint --project tsconfig.json -c tslint.json --fix",
9999
"prettier --write",

src/FileState.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const UPLOADING = "uploading";
2+
export const WAITING = "waiting";
3+
export const CANCELED = "canceled";
4+
export const RESOLVED = "resolved";
5+
export const ERROR = "error";

src/ReactUploaderSkeleton.tsx

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,95 @@
1-
import React from "react";
1+
import React, { createRef, RefObject } from "react";
2+
import * as FileState from "./FileState";
23

34
interface IReactUploaderSkeletonProps {
4-
anyText: string;
5+
anyText?: string;
6+
onClick?: () => void;
7+
}
8+
9+
interface IUploaderFileData {
10+
id: number | string;
11+
state: string;
12+
url?: string;
13+
fileData?: File;
14+
}
15+
16+
interface IReactUploaderSkeletonState {
17+
currentFiles: IUploaderFileData[];
518
}
619

720
class ReactUploaderSkeleton extends React.Component<
8-
IReactUploaderSkeletonProps
21+
IReactUploaderSkeletonProps,
22+
IReactUploaderSkeletonState
923
> {
24+
public static defaultProps = {};
25+
26+
public readonly state: IReactUploaderSkeletonState = {
27+
currentFiles: []
28+
};
29+
30+
private fileInputRef: RefObject<HTMLInputElement>;
31+
32+
constructor(props: IReactUploaderSkeletonProps) {
33+
super(props);
34+
this.fileInputRef = createRef<HTMLInputElement>();
35+
}
36+
37+
public onUploaderClick = () => {
38+
const { current } = this.fileInputRef;
39+
if (current) {
40+
current.click();
41+
}
42+
};
43+
44+
public onFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
45+
const { files } = event.target;
46+
if (files) {
47+
for (const fileIndex in files) {
48+
const currentFile = files[fileIndex];
49+
if (currentFile && /image\/.+/.test(currentFile.type)) {
50+
const fileReader = new FileReader();
51+
fileReader.addEventListener("load", () => {
52+
this.setState(({ currentFiles }) => ({
53+
currentFiles: [
54+
...currentFiles,
55+
{
56+
url: fileReader.result as string,
57+
id: currentFile.name,
58+
state: FileState.WAITING,
59+
fileData: currentFile
60+
}
61+
]
62+
}));
63+
});
64+
fileReader.readAsDataURL(files[fileIndex]);
65+
}
66+
}
67+
}
68+
};
69+
1070
public render() {
11-
return <div>{this.props.anyText}</div>;
71+
const { currentFiles } = this.state;
72+
return (
73+
<div onClick={this.onUploaderClick} className="rus">
74+
{this.props.anyText}
75+
76+
{currentFiles.map(file => (
77+
<div key={file.id}>
78+
{file.fileData && file.fileData.name}
79+
80+
<img alt={file.fileData && file.fileData.name} src={file.url} />
81+
</div>
82+
))}
83+
84+
<input
85+
className="rus_input"
86+
ref={this.fileInputRef}
87+
onChange={this.onFileChange}
88+
type="file"
89+
multiple={true}
90+
/>
91+
</div>
92+
);
1293
}
1394
}
1495

src/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
import ReactUploaderSkeleton from "./ReactUploaderSkeleton";
2-
3-
export default ReactUploaderSkeleton;
1+
import "./styles.css";
2+
export { default as ReactUploaderSkeleton } from "./ReactUploaderSkeleton";

src/styles.css

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.rus {
2+
--theme-color: hsl(262, 25%, 76%);
3+
--theme-background: hsl(262, 25%, 95%);
4+
5+
position: relative;
6+
padding: 10px;
7+
background-color: var(--theme-background);
8+
border: 2px dashed var(--theme-color);
9+
border-radius: 8px;
10+
cursor: pointer;
11+
}
12+
13+
.rus_input {
14+
position: absolute;
15+
top: 0;
16+
right: 0;
17+
bottom: 0;
18+
left: 0;
19+
width: 100%;
20+
visibility: hidden;
21+
opacity: 0;
22+
}

0 commit comments

Comments
 (0)