diff --git a/example/pages/upload-wrapper.tsx b/example/pages/upload-wrapper.tsx index 983ea36..1836e00 100644 --- a/example/pages/upload-wrapper.tsx +++ b/example/pages/upload-wrapper.tsx @@ -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 */ @@ -24,6 +29,19 @@ let PageUploadWrapper: FC<{}> = React.memo((props) => { {}}> + + + { + uploadPlugin.onUpload((files) => { + console.log("files", files); + }); + }} + > + + {uploadPlugin.ui} + ); }); @@ -43,3 +61,18 @@ let code = ` let content = ` UploadWrapper 可以包裹一个区域, 用来获取 File 对象. 得到 File 对象之后, 再通过 API 手动发送. `; + +let hooksCode = ` +let uploadPlugin = useUploadTrigger({ + acceptedFileTypes: ["jpg", "png"], +}); + + { + uploadPlugin.onUpload((files) => { + console.log("files", files); + }); + }} +> +`; diff --git a/package.json b/package.json index c8ad5f1..3cfbb26 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jimengio/files-picker", - "version": "0.0.1-a12", + "version": "0.0.1-a15", "description": "", "main": "lib/index.js", "scripts": { diff --git a/src/component/upload-wrapper.tsx b/src/component/upload-wrapper.tsx index 437deaa..d42c3c8 100644 --- a/src/component/upload-wrapper.tsx +++ b/src/component/upload-wrapper.tsx @@ -25,12 +25,13 @@ interface IProps { accept?: string; multiple?: boolean; className?: string; - onChange: (fileList: File[]) => Promise; + onChange?: (fileList: File[]) => Promise; onError?: (error: EUploadError) => void; } -let UploadWrapper: FC = React.memo((props) => { +export let useUploadTrigger = (props: IProps) => { let inputElement = useRef(null); + let filesHandlerRef = useRef<(files: File[]) => void>(null); let inputAccepts = props.accept; @@ -40,6 +41,63 @@ let UploadWrapper: FC = React.memo((props) => { } } + let ui = ( + { + 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 = React.memo((props) => { + let uploadPlugin = useUploadTrigger(props); + /** Plugins */ /** Methods */ /** Effects */ @@ -48,48 +106,11 @@ let UploadWrapper: FC = React.memo((props) => {
{ - if (inputElement.current != null) { - inputElement.current.click(); - } else { - console.error("Input element is missing in upload wrapper"); - } + uploadPlugin.onUpload(null); }} > {props.children} - - { - 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}
); }); diff --git a/src/index.ts b/src/index.ts index f223938..a29b230 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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";