Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion example/pages/upload-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import React, { FC } from "react";
import { css } from "emotion";
import { DocDemo, DocSnippet, DocBlock } from "@jimengio/doc-frame";
import { UploadWrapper } from "../../src";
import UploadWrapper, { useUploadTrigger } from "../../src/component/upload-wrapper";
import { Button } from "antd";
import { JimoButton } from "@jimengio/jimo-basics";

let PageUploadWrapper: FC<{}> = React.memo((props) => {
/** Plugins */

let uploadPlugin = useUploadTrigger({
acceptedFileTypes: ["jpg", "png"],
});

/** Methods */
/** Effects */
/** Renderers */
Expand All @@ -24,6 +29,19 @@ let PageUploadWrapper: FC<{}> = React.memo((props) => {
<JimoButton text="点击选取一个文件, 在 Console 查看" onClick={() => {}}></JimoButton>
</UploadWrapper>
</DocDemo>

<DocDemo title="Upload Trigger">
<JimoButton
text="点击选取一个文件, 在 Console 查看"
onClick={(event) => {
uploadPlugin.onUpload((files) => {
console.log("files", files);
});
}}
></JimoButton>
<DocSnippet code={hooksCode} />
{uploadPlugin.ui}
</DocDemo>
</div>
);
});
Expand All @@ -43,3 +61,18 @@ let code = `
let content = `
UploadWrapper 可以包裹一个区域, 用来获取 File 对象. 得到 File 对象之后, 再通过 API 手动发送.
`;

let hooksCode = `
let uploadPlugin = useUploadTrigger({
acceptedFileTypes: ["jpg", "png"],
});

<JimoButton
text="点击选取一个文件, 在 Console 查看"
onClick={(event) => {
uploadPlugin.onUpload((files) => {
console.log("files", files);
});
}}
></JimoButton>
`;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jimengio/files-picker",
"version": "0.0.1-a12",
"version": "0.0.1-a15",
"description": "",
"main": "lib/index.js",
"scripts": {
Expand Down
103 changes: 62 additions & 41 deletions src/component/upload-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ interface IProps {
accept?: string;
multiple?: boolean;
className?: string;
onChange: (fileList: File[]) => Promise<void>;
onChange?: (fileList: File[]) => Promise<void>;
onError?: (error: EUploadError) => void;
}

let UploadWrapper: FC<IProps> = React.memo((props) => {
export let useUploadTrigger = (props: IProps) => {
let inputElement = useRef(null);
let filesHandlerRef = useRef<(files: File[]) => void>(null);

let inputAccepts = props.accept;

Expand All @@ -40,6 +41,63 @@ let UploadWrapper: FC<IProps> = React.memo((props) => {
}
}

let ui = (
<input
title=""
className={styleInput}
ref={inputElement}
type="file"
accept={inputAccepts}
multiple={props.multiple}
onChange={async (e) => {
if (props.onChange || filesHandlerRef.current) {
const fileList = Array.from(e.target.files); // copy to array before resetting

if (fileList.length > 0) {
const files: File[] = [];

fileList.forEach((file) => {
const fileExtension = file.name.split(".").pop();
if (props.acceptedFileTypes && !props.acceptedFileTypes.includes(fileExtension)) {
if (props.onError) {
props.onError(EUploadError.unsupportedFileType);
}
message.error(interpolateLocale(uploadingLocales.unsupportedFileType, { type: props.acceptedFileTypes.join(", ") }));
return;
}
files.push(file);
});

props.onChange?.(files);
filesHandlerRef.current?.(files);
filesHandlerRef.current = null;
}
}

// reset selected files to null, or selecting same file will not trigger events
e.target.value = "";
}}
/>
);

let onUpload = (onFiles: (files: File[]) => void) => {
filesHandlerRef.current = onFiles;
if (inputElement.current != null) {
inputElement.current.click();
} else {
console.error("input element for files is not mounted!");
}
};

return {
ui,
onUpload,
};
};

let UploadWrapper: FC<IProps> = React.memo((props) => {
let uploadPlugin = useUploadTrigger(props);

/** Plugins */
/** Methods */
/** Effects */
Expand All @@ -48,48 +106,11 @@ let UploadWrapper: FC<IProps> = React.memo((props) => {
<div
className={cx(styleWrapper, props.className)}
onClick={() => {
if (inputElement.current != null) {
inputElement.current.click();
} else {
console.error("Input element is missing in upload wrapper");
}
uploadPlugin.onUpload(null);
}}
>
{props.children}

<input
title=""
className={styleInput}
ref={inputElement}
type="file"
accept={inputAccepts}
multiple={props.multiple}
onChange={async (e) => {
if (props.onChange) {
const fileList = Array.from(e.target.files); // copy to array before resetting

e.target.files = null; // without resetting, not able to trigger a change after failed

if (fileList.length > 0) {
const files: File[] = [];

fileList.forEach((file) => {
const fileExtension = file.name.split(".").pop();
if (props.acceptedFileTypes && !props.acceptedFileTypes.includes(fileExtension)) {
if (props.onError) {
props.onError(EUploadError.unsupportedFileType);
}
message.error(interpolateLocale(uploadingLocales.unsupportedFileType, { type: props.acceptedFileTypes.join(", ") }));
return;
}
files.push(file);
});

props.onChange(files);
}
}
}}
/>
{uploadPlugin.ui}
</div>
);
});
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { default as BaseUpload } from "./component/base-upload";
export { default as BaseDisplay } from "./component/base-display";
export { default as UploadWrapper } from "./component/upload-wrapper";
export { default as UploadWrapper, useUploadTrigger } from "./component/upload-wrapper";
export { default as Dropzone } from "./component/dropzone";

export { uploadByUrl, getDownloadUrl, uploadSign } from "./api";
Expand Down