diff --git a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicBasic.jsx b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicBasic.jsx index 87c1d8f102950a7b76dd9e88ab40c548b7a41a47..9a62cdfb5e94e3e482c7f766aee2dd499bb585a4 100644 --- a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicBasic.jsx +++ b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicBasic.jsx @@ -17,18 +17,18 @@ export default CodeJSFileMosaicBasic; const splittedCodeJS = `<> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info /> + <FileMosaic {...value} onDelete={removeFile} /> ) : ( - <FileInputButton onChange={updateFile} /> + <FileInputButton value={value ? [value] : []} onChange={updateFile} /> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} /> </> // file props const sampleFileProps = { id: ":0:", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", };`; @@ -38,7 +38,7 @@ import { InputButton, FileMosaic } from "@files-ui/react"; const sampleFileProps = { id: ":0:", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", }; @@ -55,29 +55,29 @@ export default function App() { return ( <div style={{display:"flex", gap:"10px"}}> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info /> + <FileMosaic {...value} onDelete={removeFile} info/> ) : ( - <FileInputButton onChange={updateFile} /> + <FileInputButton value={value ? [value] : []} onChange={updateFile} /> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} info/> </div> ); };`; const splittedCodeTS = `<> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info /> + <FileMosaic {...value} onDelete={removeFile} info/> ) : ( - <FileInputButton onChange={updateFile} /> + <FileInputButton value={value ? [value] : []} onChange={updateFile} /> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} info/> </> // file props const sampleFileProps: ExtFile = { id: ":0:", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", };`; const completeCodeTS = `import * as React from "react"; @@ -86,7 +86,7 @@ import { InputButton, FileMosaic, ExtFile } from "@files-ui/react"; const sampleFileProps:ExtFile = { id: ":0:", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", }; @@ -103,11 +103,11 @@ export default function App() { return ( <div style={{display:"flex", gap:"10px"}}> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info /> + <FileMosaic {...value} onDelete={removeFile} info/> ) : ( - <FileInputButton onChange={updateFile} /> + <FileInputButton value={value ? [value] : []} onChange={updateFile} /> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} info/> </div> ); };`; diff --git a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicDarkMode.tsx b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicDarkMode.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bdcbb484ce16bc7fc4909584fca2b957666c800d --- /dev/null +++ b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicDarkMode.tsx @@ -0,0 +1,111 @@ +import * as React from "react"; +import ShowDemoCode from "../../show-demo-code/ShowDemoCode"; + +const CodeJSFileMosaicDarkMode = () => { + return ( + <ShowDemoCode + codeCompleteJS={completeCodeJS} + codeCompleteTS={completeCodeTS} + codeSandboxJS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSandboxTS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSplittedJS={splittedCodeJS} + codeSplittedTS={splittedCodeTS} + /> + ); +}; +export default CodeJSFileMosaicDarkMode; + +const splittedCodeJS = `<> + <FileMosaic {...sampleFileProps} info onDelete={removeFile} /> + <FileMosaic {...sampleFileProps} info onDelete={removeFile} darkMode/> +</>`; +const splittedCodeTS = `<> +<FileMosaic {...sampleFileProps} info onDelete={removeFile} /> +<FileMosaic {...sampleFileProps} info onDelete={removeFile} darkMode/> +</>`; + +const completeCodeJS = `import * as React from "react"; +import { FileMosaic } from "@files-ui/react"; + +const sampleFileProps = { + id: "fileId", + size: 28 * 1024 * 1024, + type: "text/plain", + name: "file created from props.jsx", +}; +const DemoFileMosaicDarkMode = () => { + const removeFile = (id) => { + console.log("delete button clicked on file: " + id); + }; + return ( + <> + <div + style={{ + display: "flex", + justifyContent: "center", + width: "50%", + backgroundColor: "white", + padding: "10px 0", + }} + > + <FileMosaic {...sampleFileProps} info onDelete={removeFile} /> + </div> + <div + style={{ + display: "flex", + justifyContent: "center", + width: "50%", + backgroundColor: "#121212", + padding: "10px 0", + }} + > + <FileMosaic {...sampleFileProps} info darkMode onDelete={removeFile} /> + </div> + </> + ); +}; +export default DemoFileMosaicDarkMode; +`; + +const completeCodeTS = `import * as React from "react"; +import { ExtFile, FileMosaic } from "@files-ui/react"; + +const sampleFileProps: ExtFile = { + id: "fileId", + size: 28 * 1024 * 1024, + type: "text/plain", + name: "file created from props.jsx", +}; +const DemoFileMosaicDarkMode = () => { + const removeFile = (id: string | number | undefined) => { + console.log("delete button clicked on file: " + id); + }; + return ( + <> + <div + style={{ + display: "flex", + justifyContent: "center", + width: "50%", + backgroundColor: "white", + padding: "10px 0", + }} + > + <FileMosaic {...sampleFileProps} info onDelete={removeFile} /> + </div> + <div + style={{ + display: "flex", + justifyContent: "center", + width: "50%", + backgroundColor: "#121212", + padding: "10px 0", + }} + > + <FileMosaic {...sampleFileProps} info darkMode onDelete={removeFile} /> + </div> + </> + ); +}; +export default DemoFileMosaicDarkMode; +`; diff --git a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicImagePreview.tsx b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicImagePreview.tsx index 2c64abf180805d596bd16112a286841abb271598..63d00ec046e154d51b75b1eb7ef57372af907bcb 100644 --- a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicImagePreview.tsx +++ b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicImagePreview.tsx @@ -17,18 +17,18 @@ export default CodeJSFileMosaicImagePreview; const splittedCodeJS = `<> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info preview/> + <FileMosaic {...value} onDelete={removeFile} info preview/> ) : ( <FileInputButton onChange={updateFile} accept="image/*"/> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} info/> </> // file props const sampleFileProps = { id: "fileId", size: 28 * 1024 * 1024, - type: "image/gif", + type: "image/jpeg", name: "Thor arrives wakanda.jpg", imageUrl:"https://cdn.wallpapersafari.com/0/95/1zms6H.jpg" };`; @@ -39,7 +39,7 @@ import { InputButton, FileMosaic } from "@files-ui/react"; const sampleFileProps = { id: "fileId", size: 28 * 1024 * 1024, - type: "image/gif", + type: "image/jpeg", name: "Thor arrives wakanda.jpg", imageUrl:"https://cdn.wallpapersafari.com/0/95/1zms6H.jpg" }; @@ -57,29 +57,29 @@ export default function App() { return ( <div style={{display:"flex", gap:"10px"}}> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info preview/> + <FileMosaic {...value} onDelete={removeFile} info preview/> ) : ( <FileInputButton onChange={updateFile} accept="image/*"/> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} info/> </div> ); };`; const splittedCodeTS = `<> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info preview/> + <FileMosaic {...value} onDelete={removeFile} info preview/> ) : ( <FileInputButton onChange={updateFile} accept="image/*"/> )} -<FileMosaic {...sampleFileProps} alwaysActive info /> +<FileMosaic {...sampleFileProps} info/> </> // file props const sampleFileProps: ExtFile = { id: "fileId", size: 28 * 1024 * 1024, - type: "image/gif", + type: "image/jpeg", name: "Thor arrives wakanda.jpg", imageUrl:"https://cdn.wallpapersafari.com/0/95/1zms6H.jpg" };`; @@ -89,7 +89,7 @@ import { InputButton, FileMosaic, ExtFile } from "@files-ui/react"; const sampleFileProps: ExtFile = { id: "fileId", size: 28 * 1024 * 1024, - type: "image/gif", + type: "image/jpeg", name: "Thor arrives wakanda.jpg", imageUrl:"https://cdn.wallpapersafari.com/0/95/1zms6H.jpg" }; @@ -107,11 +107,11 @@ export default function App() { return ( <div style={{display:"flex", gap:"10px"}}> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info preview/> + <FileMosaic {...value} onDelete={removeFile} info preview/> ) : ( <FileInputButton onChange={updateFile} accept="image/*"/> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} info/> </div> ); };`; diff --git a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicLocalization.jsx b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicLocalization.jsx new file mode 100644 index 0000000000000000000000000000000000000000..a4d570d98170ed6cfeb3917a65597e1776ea5f9b --- /dev/null +++ b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicLocalization.jsx @@ -0,0 +1,266 @@ +import * as React from "react"; +import ShowDemoCode from "../../show-demo-code/ShowDemoCode"; + +const CodeJSFileMosaicLocalization = (props) => { + return ( + <ShowDemoCode + codeCompleteJS={completeCodeJS} + codeCompleteTS={completeCodeTS} + codeSandboxJS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSandboxTS="https://codesandbox.io/s/dropzone-ui-basic-3j01v" + codeSplittedJS={splittedCodeJS} + codeSplittedTS={splittedCodeTS} + /> + ); +}; +export default CodeJSFileMosaicLocalization; + +const splittedCodeJS = ``; +const splittedCodeTS = ``; + + +const completeCodeJS = `import * as React from "react"; +import { FileMosaic } from "@files-ui/react"; +import { Autocomplete, TextField } from "@mui/material"; + +const DemoFileMosaicLocalization = () => { + const [localization, setLocalization] = React.useState(undefined); + + const hadleSelect = (value) => { + console.log(value); + setLocalization(value?.value); + }; + return ( + <> + <Autocomplete + disablePortal + autoSelect + size="small" + onChange={(e, value) => hadleSelect(value)} + id="combo-box-demo" + options={languages} + sx={{ width: 300 }} + getOptionLabel={(option) => option.language} + renderInput={(params) => <TextField {...params} label="Localization" />} + /> + <div + style={{ + display: "flex", + flexWrap: "wrap", + justifyContent: "space-evenly", + width: "100%", + gap: "50px", + }} + > + {extFiles.map((extFile, index) => ( + <FileMosaic + key={index} + {...extFile} + localization={localization} + onDelete={() => {}} + info + /> + ))} + </div> + </> + ); +}; +export default DemoFileMosaicLocalization; + +const languages = [ + { language: "Español: ES-es", value: "ES-es" }, + { language: "English: EN-en", value: "EN-en" }, + { language: "French: FR-fr", value: "FR-fr" }, + { language: "Italian: IT-it", value: "IT-it" }, + { language: "Portuguese: PT-pt", value: "PT-pt" }, + { language: "Russian: RU-ru", value: "RU-ru" }, + { language: "Chinese(simplified): ZH-cn", value: "ZH-cn" }, + { language: "Chinese(traditional): ZH-hk", value: "ZH-hk" }, +]; +const extFiles = [ + { + id: 0, + name: "file_localization.docx", + size: 28 * 1024, + errors: ["pdf not allowed", "file is too big"], + }, + { + id: 1, + valid: false, + name: "file_localization.docx", + + size: 28 * 1024, + errors: ["pdf not allowed", "file is too big"], + }, + { + id: 2, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + }, + { + id: 3, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "preparing", + }, + { + id: 4, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "uploading", + progress: 28, + }, + { + id: 5, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "aborted", + uploadMessage: "Upload was aborted", + }, + { + id: 6, + valid: false, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "error", + uploadMessage: "there was an error on the server", + }, + { + id: 7, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "success", + uploadMessage: "files-ui <3", + }, +];`; + +const completeCodeTS = `import * as React from "react"; +import { ExtFile, FileMosaic, Localization } from "@files-ui/react"; +import { Autocomplete, TextField } from "@mui/material"; + +const DemoFileMosaicLocalization = () => { + const [localization, setLocalization] = React.useState< + Localization | undefined + >(undefined); + + const hadleSelect = (value: LanguageItem | null) => { + console.log(value); + setLocalization(value?.value); + }; + + return ( + <> + <Autocomplete + disablePortal + autoSelect + size="small" + onChange={(e, value) => hadleSelect(value as LanguageItem)} + id="combo-box-demo" + options={languages} + sx={{ width: 300 }} + getOptionLabel={(option) => option.language} + renderInput={(params) => <TextField {...params} label="Localization" />} + /> + <div + style={{ + display: "flex", + flexWrap: "wrap", + justifyContent: "space-evenly", + width: "100%", + gap: "50px", + }} + > + {extFiles.map((extFile, index) => ( + <FileMosaic + key={index} + {...extFile} + localization={localization} + onDelete={() => {}} + info + /> + ))} + </div> + </> + ); +}; +export default DemoFileMosaicLocalization; + +interface LanguageItem { + language: string; + value: Localization; +} + +const languages = [ + { language: "Español: ES-es", value: "ES-es" }, + { language: "English: EN-en", value: "EN-en" }, + { language: "French: FR-fr", value: "FR-fr" }, + { language: "Italian: IT-it", value: "IT-it" }, + { language: "Portuguese: PT-pt", value: "PT-pt" }, + { language: "Russian: RU-ru", value: "RU-ru" }, + { language: "Chinese(simplified): ZH-cn", value: "ZH-cn" }, + { language: "Chinese(traditional): ZH-hk", value: "ZH-hk" }, +]; +const extFiles: ExtFile[] = [ + { + id: 0, + name: "file_localization.docx", + size: 28 * 1024, + errors: ["pdf not allowed", "file is too big"], + }, + { + id: 1, + valid: false, + name: "file_localization.docx", + + size: 28 * 1024, + errors: ["pdf not allowed", "file is too big"], + }, + { + id: 2, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + }, + { + id: 3, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "preparing", + }, + { + id: 4, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "uploading", + progress: 28, + }, + { + id: 5, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "aborted", + uploadMessage: "Upload was aborted", + }, + { + id: 6, + valid: false, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "error", + uploadMessage: "there was an error on the server", + }, + { + id: 7, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "success", + uploadMessage: "files-ui <3", + }, +];`; diff --git a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicUploadStatus.jsx b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicUploadStatus.jsx index bc7027d5035c76629ae6d6e6ec0bc02c8585d77c..0ee972514373b1bef851907506b6c5d59c6c71eb 100644 --- a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicUploadStatus.jsx +++ b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicUploadStatus.jsx @@ -15,135 +15,254 @@ const CodeJSFileMosaicUploadStatus = () => { }; export default CodeJSFileMosaicUploadStatus; -const splittedCodeJS = `<> - {sampleFilesProps.map((extFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> - ))} -</> - -// file props -const sampleFilesProps = [ - { - id: "fileId-1", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "file created from props.jsx", - }, - { - id: "fileId-2", - size: 28 * 1024 * 1024, - type: "image/png", - name: "valid file created from props.png", - valid: true, - }, - { - id: "fileId-3", - size: 28 * 1024 * 1024, - type: "image/jpeg", - name: "non valid file created from props.jpg", - valid: false, - }, -];`; +const splittedCodeJS = ``; + +const splittedCodeTS = ``; const completeCodeJS = `import * as React from "react"; -import { FileMosaic } from "../../../files-ui"; +import { + FileMosaic, + useFakeProgress, +} from "@files-ui/react"; -const sampleFilesProps = [ - { - id: "fileId-1", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "file created from props.jsx", - }, +const DemoFileMosaicUploadStatus = () => { + const progress = useFakeProgress(); + + const [status1, setStatus1] = React.useState("uploading"); + const [status2, setStatus2] = React.useState("uploading"); + const [status3, setStatus3] = React.useState("uploading"); + + React.useEffect(() => { + //schedule an interval + const _myInterval = setInterval(() => { + //set the uploadstatus result + setStatus1((_status) => setNextUploadState(_status, "aborted")); + setStatus2((_status) => setNextUploadState(_status, "error")); + setStatus3((_status) => setNextUploadState(_status, "success")); + }, 5000); + + //clean + return () => { + console.log("clear interval", _myInterval); + clearInterval(_myInterval); + }; + }, []); + + const handleCancel = (id) => { + console.log("Upload canceled in file: " + id); + }; + const handleAbort = (id) => { + console.log("Upload aborted in file: " + id); + }; + return ( + <> + <FlexRowContainer> + <FileMosaic {...preparingFile} /> + <FileMosaic {...preparingFile} onCancel={handleCancel} /> + </FlexRowContainer> + + <FlexRowContainer> + <FileMosaic {...uploadingFile} /> + <FileMosaic {...uploadingFile} progress={progress} /> + <FileMosaic {...uploadingFile} onAbort={handleAbort} /> + <FileMosaic {...uploadingFile} onAbort={handleAbort} progress={progress} /> + </FlexRowContainer> + + <FlexRowContainer> + <FileMosaic {...uploadResultFiles[0]} uploadStatus={status1} /> + <FileMosaic {...uploadResultFiles[1]} uploadStatus={status2} /> + <FileMosaic {...uploadResultFiles[2]} uploadStatus={status3} /> + </FlexRowContainer> + </> + ); +}; +export default DemoFileMosaicUploadStatus; + +const FlexRowContainer = ({ children }) => { + return ( + <div + style={{ + display: "flex", + flexWrap: "wrap", + justifyContent: "space-evenly", + width: "100%", + }} + > + {children} + </div> + ); +}; + +const setNextUploadState = ( + prevState, + nextStatus +) => { + if (prevState === "uploading") return nextStatus; + else return "uploading"; +}; + +const preparingFile = { + id: "fileId-0", + size: 28 * 1024 * 1024, + type: "text/plain", + name: "preparing file.jsx", + uploadStatus: "preparing", +}; + +const uploadingFile = { + id: "fileId-1", + size: 28 * 1024 * 1024, + type: "image/png", + name: "uploading file.png", + uploadStatus: "uploading", +}; + +const uploadResultFiles = [ { id: "fileId-2", size: 28 * 1024 * 1024, - type: "image/png", - name: "valid file created from props.png", - valid: true, + type: "image/gif", + name: "upload aborted file.gif", + uploadMessage: "Upload was aborted by the user", }, { id: "fileId-3", size: 28 * 1024 * 1024, type: "image/jpeg", - name: "non valid file created from props.jpg", - valid: false, + name: "upload with error file.jpg", + uploadMessage: + "File couldn't be uploaded to Files-ui earthquakes. File was too big.", + }, + { + id: "fileId-4", + size: 28 * 1024 * 1024, + type: "image/png", + name: "successfully uploaded file.png", + uploadMessage: "File was uploaded correctly to Files-ui earthquakes", }, -]; +];`; + +const completeCodeTS = `import * as React from "react"; +import { + FileMosaic, + useFakeProgress, + ExtFile, + UPLOADSTATUS, +} from "@files-ui/react"; + +const DemoFileMosaicUploadStatus = () => { + const progress = useFakeProgress(); + + const [status1, setStatus1] = React.useState<UPLOADSTATUS>("uploading"); + const [status2, setStatus2] = React.useState<UPLOADSTATUS>("uploading"); + const [status3, setStatus3] = React.useState<UPLOADSTATUS>("uploading"); + + React.useEffect(() => { + //schedule an interval + const _myInterval = setInterval(() => { + //set the uploadstatus result + setStatus1((_status) => setNextUploadState(_status, "aborted")); + setStatus2((_status) => setNextUploadState(_status, "error")); + setStatus3((_status) => setNextUploadState(_status, "success")); + }, 5000); + + //clean + return () => { + console.log("clear interval", _myInterval); + clearInterval(_myInterval as NodeJS.Timer); + }; + }, []); -const DemoFileMosaicValidation = () => { + const handleCancel = (id: string | number | undefined) => { + console.log("Upload canceled in file: " + id); + }; + const handleAbort = (id: string | number | undefined) => { + console.log("Upload aborted in file: " + id); + }; return ( <> - {sampleFilesProps.map((extFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> - ))} + <FlexRowContainer> + <FileMosaic {...preparingFile} /> + <FileMosaic {...preparingFile} onCancel={handleCancel} /> + </FlexRowContainer> + + <FlexRowContainer> + <FileMosaic {...uploadingFile} /> + <FileMosaic {...uploadingFile} progress={progress} /> + <FileMosaic {...uploadingFile} onAbort={handleAbort} /> + <FileMosaic {...uploadingFile} onAbort={handleAbort} progress={progress} /> + </FlexRowContainer> + + <FlexRowContainer> + <FileMosaic {...uploadResultFiles[0]} uploadStatus={status1} /> + <FileMosaic {...uploadResultFiles[1]} uploadStatus={status2} /> + <FileMosaic {...uploadResultFiles[2]} uploadStatus={status3} /> + </FlexRowContainer> </> ); }; -export default DemoFileMosaicValidation;`; - -const splittedCodeTS = `<> - {sampleFilesProps.map((extFile:ExtFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> - ))} -</> - -// file props -const sampleFilesProps:ExtFile[] = [ - { - id: "fileId-1", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "file created from props.jsx", - }, - { - id: "fileId-2", - size: 28 * 1024 * 1024, - type: "image/png", - name: "valid file created from props.png", - valid: true, - }, - { - id: "fileId-3", - size: 28 * 1024 * 1024, - type: "image/jpeg", - name: "non valid file created from props.jpg", - valid: false, - }, -];`; -const completeCodeTS = `import * as React from "react"; -import { FileMosaic, ExtFile } from "../../../files-ui"; +export default DemoFileMosaicUploadStatus; -const sampleFilesProps: ExtFile[] = [ - { - id: "fileId-1", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "file created from props.jsx", - }, +const FlexRowContainer = (props: { children: React.ReactNode }) => { + return ( + <div + style={{ + display: "flex", + flexWrap: "wrap", + justifyContent: "space-evenly", + width: "100%", + }} + > + {props.children} + </div> + ); +}; + +const setNextUploadState = ( + prevState: UPLOADSTATUS, + nextStatus: UPLOADSTATUS +): UPLOADSTATUS => { + if (prevState === "uploading") return nextStatus; + else return "uploading"; +}; + +const preparingFile: ExtFile = { + id: "fileId-0", + size: 28 * 1024 * 1024, + type: "text/plain", + name: "preparing file.jsx", + uploadStatus: "preparing", +}; + +const uploadingFile: ExtFile = { + id: "fileId-1", + size: 28 * 1024 * 1024, + type: "image/png", + name: "uploading file.png", + uploadStatus: "uploading", +}; + +const uploadResultFiles: ExtFile[] = [ { id: "fileId-2", size: 28 * 1024 * 1024, - type: "image/png", - name: "valid file created from props.png", - valid: true, + type: "image/gif", + name: "upload aborted file.gif", + uploadMessage: "Upload was aborted by the user", }, { id: "fileId-3", size: 28 * 1024 * 1024, type: "image/jpeg", - name: "non valid file created from props.jpg", - valid: false, + name: "upload with error file.jpg", + uploadMessage: + "File couldn't be uploaded to Files-ui earthquakes. File was too big.", }, -]; - -const DemoFileMosaicValidation = () => { - return ( - <> - {sampleFilesProps.map((extFile: ExtFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> - ))} - </> - ); -}; -export default DemoFileMosaicValidation;`; + { + id: "fileId-4", + size: 28 * 1024 * 1024, + type: "image/png", + name: "successfully uploaded file.png", + uploadMessage: "File was uploaded correctly to Files-ui earthquakes", + }, +];`; diff --git a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicValidation.jsx b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicValidation.jsx index 77645d3a6413384f048bf4739195a957a03cc82f..435488cb7cc7f0dadaeffbd45acee903c758b373 100644 --- a/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicValidation.jsx +++ b/src/components/demo-components/filemosaic-demo/CodeJSFileMosaicValidation.jsx @@ -15,44 +15,28 @@ const CodeJSFileMosaicValidation = () => { }; export default CodeJSFileMosaicValidation; -const splittedCodeJS = `<> - {sampleFilesProps.map((extFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> - ))} -</> - -// file props -const sampleFilesProps = [ - { - id: "fileId-1", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "file created from props.jsx", - }, - { - id: "fileId-2", - size: 28 * 1024 * 1024, - type: "image/png", - name: "valid file created from props.png", - valid: true, - }, - { - id: "fileId-3", - size: 28 * 1024 * 1024, - type: "image/jpeg", - name: "non valid file created from props.jpg", - valid: false, - }, -];`; +const splittedCodeJS = ``; +const splittedCodeTS = ``; const completeCodeJS = `import * as React from "react"; import { FileMosaic } from "../../../files-ui"; +const DemoFileMosaicValidation = () => { + return ( + <div style={{display:"flex", gap:"10px"}}> + {sampleFilesProps.map((extFile) => ( + <FileMosaic key={extFile.id} valid={extFile.valid} {...extFile} info/> + ))} + </div> + ); +}; +export default DemoFileMosaicValidation; + const sampleFilesProps = [ { id: "fileId-1", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", }, { @@ -60,65 +44,37 @@ const sampleFilesProps = [ size: 28 * 1024 * 1024, type: "image/png", name: "valid file created from props.png", - valid: true, + valid: false, + errors: ["File is too big", "File type is not allowed"] }, { id: "fileId-3", size: 28 * 1024 * 1024, type: "image/jpeg", name: "non valid file created from props.jpg", - valid: false, + valid: true, }, -]; +];`; + +const completeCodeTS = `import * as React from "react"; +import { FileMosaic, ExtFile } from "../../../files-ui"; const DemoFileMosaicValidation = () => { return ( - <> - {sampleFilesProps.map((extFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> + <div style={{display:"flex", gap:"10px"}}> + {sampleFilesProps.map((extFile: ExtFile) => ( + <FileMosaic key={extFile.id} valid={extFile.valid} {...extFile} info/> ))} - </> + </div> ); }; -export default DemoFileMosaicValidation;`; - -const splittedCodeTS = `<> - {sampleFilesProps.map((extFile:ExtFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> - ))} -</> - -// file props -const sampleFilesProps:ExtFile[] = [ - { - id: "fileId-1", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "file created from props.jsx", - }, - { - id: "fileId-2", - size: 28 * 1024 * 1024, - type: "image/png", - name: "valid file created from props.png", - valid: true, - }, - { - id: "fileId-3", - size: 28 * 1024 * 1024, - type: "image/jpeg", - name: "non valid file created from props.jpg", - valid: false, - }, -];`; -const completeCodeTS = `import * as React from "react"; -import { FileMosaic, ExtFile } from "../../../files-ui"; +export default DemoFileMosaicValidation; const sampleFilesProps: ExtFile[] = [ { id: "fileId-1", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", }, { @@ -126,24 +82,14 @@ const sampleFilesProps: ExtFile[] = [ size: 28 * 1024 * 1024, type: "image/png", name: "valid file created from props.png", - valid: true, + valid: false, + errors: ["File is too big", "File type is not allowed"] }, { id: "fileId-3", size: 28 * 1024 * 1024, type: "image/jpeg", name: "non valid file created from props.jpg", - valid: false, + valid: true, }, -]; - -const DemoFileMosaicValidation = () => { - return ( - <> - {sampleFilesProps.map((extFile: ExtFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> - ))} - </> - ); -}; -export default DemoFileMosaicValidation;`; +];`; diff --git a/src/components/demo-components/filemosaic-demo/DemoFileMosaicBasic.jsx b/src/components/demo-components/filemosaic-demo/DemoFileMosaicBasic.jsx index 3f9bf1d8202b102cd6b21e978bb40a686fd7f8e3..20bb19ebcde31b6421015b16034230206e515234 100644 --- a/src/components/demo-components/filemosaic-demo/DemoFileMosaicBasic.jsx +++ b/src/components/demo-components/filemosaic-demo/DemoFileMosaicBasic.jsx @@ -4,7 +4,7 @@ import { FileInputButton, FileMosaic } from "../../../files-ui"; const sampleFileProps = { id: "fileId", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", }; const DemoFileMosaicBasic = (props) => { @@ -21,11 +21,11 @@ const DemoFileMosaicBasic = (props) => { return ( <> {value ? ( - <FileMosaic {...value} onDelete={removeFile} alwaysActive info preview/> + <FileMosaic {...value} onDelete={removeFile} info/> ) : ( - <FileInputButton value={value?[value]:[]} onChange={updateFile} /> + <FileInputButton value={value ? [value] : []} onChange={updateFile} /> )} - <FileMosaic {...sampleFileProps} alwaysActive info preview/> + <FileMosaic {...sampleFileProps} info/> </> ); }; diff --git a/src/components/demo-components/filemosaic-demo/DemoFileMosaicDarkMode.tsx b/src/components/demo-components/filemosaic-demo/DemoFileMosaicDarkMode.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a878f3fa86f042b278fbd84c9add44021d3925ed --- /dev/null +++ b/src/components/demo-components/filemosaic-demo/DemoFileMosaicDarkMode.tsx @@ -0,0 +1,41 @@ +import * as React from "react"; +import { ExtFile, FileMosaic } from "../../../files-ui"; + +const sampleFileProps: ExtFile = { + id: "fileId", + size: 28 * 1024 * 1024, + type: "text/plain", + name: "file created from props.jsx", +}; +const DemoFileMosaicDarkMode = () => { + const removeFile = (id: string | number | undefined) => { + console.log("delete button clicked on file: " + id); + }; + return ( + <> + <div + style={{ + display: "flex", + justifyContent: "center", + width: "50%", + backgroundColor: "white", + padding: "15px 0", + }} + > + <FileMosaic {...sampleFileProps} info onDelete={removeFile} /> + </div> + <div + style={{ + display: "flex", + justifyContent: "center", + width: "50%", + backgroundColor: "#121212", + padding: "15px 0", + }} + > + <FileMosaic {...sampleFileProps} info darkMode onDelete={removeFile} /> + </div> + </> + ); +}; +export default DemoFileMosaicDarkMode; diff --git a/src/components/demo-components/filemosaic-demo/DemoFileMosaicFileIcons.jsx b/src/components/demo-components/filemosaic-demo/DemoFileMosaicFileIcons.jsx new file mode 100644 index 0000000000000000000000000000000000000000..3432c4c1646342f936e9c0de7a45dc416810fdb9 --- /dev/null +++ b/src/components/demo-components/filemosaic-demo/DemoFileMosaicFileIcons.jsx @@ -0,0 +1,37 @@ +import * as React from "react"; +import { FileMosaic,createListOfMultiTypeFile } from "../../../files-ui"; + +/* const sampleFileProps = { + id: "fileId", + size: 28 * 1024 * 1024, + type: "text/plain", + name: "file created from props.jsx", +}; */ +const DemoFileMosaicFileIcons = () => { + const [files, setFiles] = React.useState([]); + + const removeFile = (id) => { + console.log("delete button clicked on file: " + id); + }; + + React.useEffect(() => { + const validateFiles = createListOfMultiTypeFile(28*1024*1024).map((x, index) => { + return { + id:index, + size: 28 * 1024 * 1024, + type: x.type, + name: x.name, + }; + }); + //console.log(validateFiles); + setFiles(validateFiles); + }, []); + return ( + <> + {files.map((f, index) => ( + <FileMosaic {...f} key={f.id} onDelete={removeFile} info /> + ))} + </> + ); +}; +export default DemoFileMosaicFileIcons; diff --git a/src/components/demo-components/filemosaic-demo/DemoFileMosaicImagePreview.tsx b/src/components/demo-components/filemosaic-demo/DemoFileMosaicImagePreview.tsx index 5b0610bca92675a7d3c13c353ca637b1287a2d92..f59b0708432269eee2a25f4c21ac885920202ec7 100644 --- a/src/components/demo-components/filemosaic-demo/DemoFileMosaicImagePreview.tsx +++ b/src/components/demo-components/filemosaic-demo/DemoFileMosaicImagePreview.tsx @@ -27,17 +27,15 @@ const DemoFileMosaicImagePreview: React.FC<DemoFileMosaicImagePreviewProps> = ( return ( <> {value ? ( - <FileMosaic - {...value} - onDelete={removeFile} - alwaysActive - info - preview - /> + <FileMosaic {...value} onDelete={removeFile} info preview/> ) : ( - <FileInputButton value={value ? [value] : []} onChange={updateFile} accept="image/*"/> + <FileInputButton + value={value ? [value] : []} + onChange={updateFile} + accept="image/*" + /> )} - <FileMosaic {...sampleFileProps} alwaysActive info /> + <FileMosaic {...sampleFileProps} info/> </> ); }; diff --git a/src/components/demo-components/filemosaic-demo/DemoFileMosaicLocalization.tsx b/src/components/demo-components/filemosaic-demo/DemoFileMosaicLocalization.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6354a3d637a5e50fd7009958a3ae2802f32c7651 --- /dev/null +++ b/src/components/demo-components/filemosaic-demo/DemoFileMosaicLocalization.tsx @@ -0,0 +1,126 @@ +import * as React from "react"; +import { ExtFile, FileMosaic, Localization } from "../../../files-ui"; +import { Autocomplete, TextField } from "@mui/material"; + +const DemoFileMosaicLocalization = () => { + const [localization, setLocalization] = React.useState< + Localization | undefined + >(undefined); + + const hadleSelect = (value: LanguageItem | null) => { + console.log(value); + setLocalization(value?.value); + }; + + return ( + <> + <Autocomplete + disablePortal + autoSelect + size="small" + onChange={(e, value) => hadleSelect(value as LanguageItem)} + id="combo-box-demo" + options={languages} + sx={{ width: 300 }} + getOptionLabel={(option) => option.language} + renderInput={(params) => <TextField {...params} label="Localization" />} + /> + <div + style={{ + display: "flex", + flexWrap: "wrap", + justifyContent: "space-evenly", + width: "100%", + gap: "50px", + }} + > + {extFiles.map((extFile, index) => ( + <FileMosaic + key={index} + {...extFile} + localization={localization} + onDelete={() => {}} + info + /> + ))} + </div> + </> + ); +}; +export default DemoFileMosaicLocalization; + +interface LanguageItem { + language: string; + value: Localization; +} + +const languages = [ + { language: "Español: ES-es", value: "ES-es" }, + { language: "English: EN-en", value: "EN-en" }, + { language: "French: FR-fr", value: "FR-fr" }, + { language: "Italian: IT-it", value: "IT-it" }, + { language: "Portuguese: PT-pt", value: "PT-pt" }, + { language: "Russian: RU-ru", value: "RU-ru" }, + { language: "Chinese(simplified): ZH-cn", value: "ZH-cn" }, + { language: "Chinese(traditional): ZH-hk", value: "ZH-hk" }, +]; +const extFiles: ExtFile[] = [ + { + id: 0, + name: "file_localization.docx", + size: 28 * 1024, + errors: ["pdf not allowed", "file is too big"], + }, + { + id: 1, + valid: false, + name: "file_localization.docx", + + size: 28 * 1024, + errors: ["pdf not allowed", "file is too big"], + }, + { + id: 2, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + }, + { + id: 3, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "preparing", + }, + { + id: 4, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "uploading", + progress: 28, + }, + { + id: 5, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "aborted", + uploadMessage: "Upload was aborted", + }, + { + id: 6, + valid: false, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "error", + uploadMessage: "there was an error on the server", + }, + { + id: 7, + valid: true, + name: "file_localization.docx", + size: 28 * 1024, + uploadStatus: "success", + uploadMessage: "files-ui <3", + }, +]; diff --git a/src/components/demo-components/filemosaic-demo/DemoFileMosaicUploadStatus.tsx b/src/components/demo-components/filemosaic-demo/DemoFileMosaicUploadStatus.tsx index eaeaa2b32e65a5e295f12968b7c454a5d621c572..ed044dff66fa76e7a871647996712dd8e1c5edb2 100644 --- a/src/components/demo-components/filemosaic-demo/DemoFileMosaicUploadStatus.tsx +++ b/src/components/demo-components/filemosaic-demo/DemoFileMosaicUploadStatus.tsx @@ -1,154 +1,128 @@ import * as React from "react"; -import { FileMosaic } from "../../../files-ui"; -import { ExtFile, getRandomInt } from "../../../files-ui/core"; -const preparingFiles: ExtFile[] = [ - { - id: "fileId-1", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "default preparing file.jsx", - uploadStatus: "preparing", - }, - { - id: "fileId-2", - size: 28 * 1024 * 1024, - type: "plain/javascript", - name: "preparing file that can be stopped.jsx", - uploadStatus: "preparing", - }, -]; -const uploadingFiles: ExtFile[] = [ - { - size: 28 * 1024 * 1024, - type: "image/png", - name: "non abortable with no specific progress.png", - valid: true, - uploadStatus: "uploading", - }, - { - size: 28 * 1024 * 1024, - type: "image/png", - name: "non abortable with specific progress.png", - valid: true, - uploadStatus: "uploading", - progress: 56, - }, - { - size: 28 * 1024 * 1024, - type: "image/png", - name: "abortable with no specific progress.png", - valid: true, - uploadStatus: "uploading", - }, - { - size: 28 * 1024 * 1024, - type: "image/png", - name: "abortable with specific progress.png", - valid: true, - uploadStatus: "uploading", - progress: 56, - }, -]; -const uploadResulFiles: ExtFile[] = [ - { - size: 28 * 1024 * 1024, - type: "image/jpeg", - name: "non valid file created from props.jpg", - uploadStatus: "aborted", - uploadMessage: "Upload was aborted by the user", - }, - { - size: 28 * 1024 * 1024, - type: "image/jpeg", - name: "non valid file created from props.jpg", - uploadStatus: "error", - uploadMessage: - "File couldn't be uploaded to Files-ui earthquakes. File was too big.", - }, - { - size: 28 * 1024 * 1024, - type: "image/jpeg", - name: "non valid file created from props.jpg", - uploadStatus: "success", - uploadMessage: "File was uploaded correctly to Files-ui earthquakes", - }, -]; +import { + FileMosaic, + useFakeProgress, + ExtFile, + UPLOADSTATUS, +} from "../../../files-ui"; -const FlexRowContainer = (props: { children: React.ReactNode }) => { - return ( - <div - style={{ - display: "flex", - flexWrap: "wrap", - justifyContent: "space-evenly", - width: "100%", - }} - > - {props.children} - </div> - ); -}; const DemoFileMosaicUploadStatus = () => { - const [progress, setProgress] = React.useState(28); - const [progress2, setProgress2] = React.useState(28); + const progress = useFakeProgress(); + + const [status1, setStatus1] = React.useState<UPLOADSTATUS>("uploading"); + const [status2, setStatus2] = React.useState<UPLOADSTATUS>("uploading"); + const [status3, setStatus3] = React.useState<UPLOADSTATUS>("uploading"); + React.useEffect(() => { + //schedule an interval const _myInterval = setInterval(() => { - setProgress((_progress) => { - if (_progress === 100) { - return 0; - } - const offset = getRandomInt(5, 14); - const newProgress = _progress + offset; - if (newProgress > 100) { - return 100; - } else { - return newProgress; - } - }); - setProgress2((_progress) => { - if (_progress === 100) { - return 0; - } - const offset = getRandomInt(10, 24); - const newProgress = _progress + offset; - if (newProgress > 100) { - return 100; - } else { - return newProgress; - } - }); - }, 2000); + //set the uploadstatus result + setStatus1((_status) => setNextUploadState(_status, "aborted")); + setStatus2((_status) => setNextUploadState(_status, "error")); + setStatus3((_status) => setNextUploadState(_status, "success")); + }, 5000); + //clean return () => { console.log("clear interval", _myInterval); clearInterval(_myInterval as NodeJS.Timer); }; }, []); + + const handleCancel = (id: string | number | undefined) => { + console.log("Upload canceled in file: " + id); + }; + const handleAbort = (id: string | number | undefined) => { + console.log("Upload aborted in file: " + id); + }; return ( <> <FlexRowContainer> - <FileMosaic {...preparingFiles[0]} /> - <FileMosaic {...preparingFiles[1]} onCancel={() => {}} /> + <FileMosaic {...preparingFile} /> + <FileMosaic {...preparingFile} onCancel={handleCancel} /> </FlexRowContainer> <FlexRowContainer> - <FileMosaic {...uploadingFiles[0]} /> - <FileMosaic {...uploadingFiles[0]} progress={progress} /> - <FileMosaic {...uploadingFiles[2]} onAbort={() => {}} /> + <FileMosaic {...uploadingFile} /> + <FileMosaic {...uploadingFile} progress={progress} /> + <FileMosaic {...uploadingFile} onAbort={handleAbort} /> <FileMosaic - {...uploadingFiles[3]} - onAbort={() => {}} - progress={progress2} + {...uploadingFile} + onAbort={handleAbort} + progress={progress} /> </FlexRowContainer> <FlexRowContainer> - <FileMosaic {...uploadResulFiles[0]} resultOnTooltip /> - <FileMosaic {...uploadResulFiles[1]} resultOnTooltip /> - <FileMosaic {...uploadResulFiles[2]} resultOnTooltip /> - <FileMosaic {...uploadResulFiles[3]} resultOnTooltip /> + <FileMosaic {...uploadResultFiles[0]} uploadStatus={status1} /> + <FileMosaic {...uploadResultFiles[1]} uploadStatus={status2} /> + <FileMosaic {...uploadResultFiles[2]} uploadStatus={status3} /> </FlexRowContainer> </> ); }; export default DemoFileMosaicUploadStatus; + +const FlexRowContainer = (props: { children: React.ReactNode }) => { + return ( + <div + style={{ + display: "flex", + flexWrap: "wrap", + justifyContent: "space-evenly", + width: "100%", + }} + > + {props.children} + </div> + ); +}; + +const setNextUploadState = ( + prevState: UPLOADSTATUS, + nextStatus: UPLOADSTATUS +): UPLOADSTATUS => { + if (prevState === "uploading") return nextStatus; + else return "uploading"; +}; + +const preparingFile: ExtFile = { + id: "fileId-0", + size: 28 * 1024 * 1024, + type: "text/plain", + name: "preparing file.jsx", + uploadStatus: "preparing", +}; + +const uploadingFile: ExtFile = { + id: "fileId-1", + size: 28 * 1024 * 1024, + type: "image/png", + name: "uploading file.png", + uploadStatus: "uploading", +}; + +const uploadResultFiles: ExtFile[] = [ + { + id: "fileId-2", + size: 28 * 1024 * 1024, + type: "image/gif", + name: "upload aborted file.gif", + uploadMessage: "Upload was aborted by the user", + }, + { + id: "fileId-3", + size: 28 * 1024 * 1024, + type: "image/jpeg", + name: "upload with error file.jpg", + uploadMessage: + "File couldn't be uploaded to Files-ui earthquakes. File was too big.", + }, + { + id: "fileId-4", + size: 28 * 1024 * 1024, + type: "image/png", + name: "successfully uploaded file.png", + uploadMessage: "File was uploaded correctly to Files-ui earthquakes", + }, +]; diff --git a/src/components/demo-components/filemosaic-demo/DemoFileMosaicValidation.jsx b/src/components/demo-components/filemosaic-demo/DemoFileMosaicValidation.jsx index 93df5d57eee3e6c7faa65cb96ba82b082efd42c0..0c3d1a9fb6c579ab89d21074d52a30fa0ef0053d 100644 --- a/src/components/demo-components/filemosaic-demo/DemoFileMosaicValidation.jsx +++ b/src/components/demo-components/filemosaic-demo/DemoFileMosaicValidation.jsx @@ -5,7 +5,7 @@ const sampleFilesProps = [ { id: "fileId-1", size: 28 * 1024 * 1024, - type: "plain/javascript", + type: "text/plain", name: "file created from props.jsx", }, { @@ -14,6 +14,7 @@ const sampleFilesProps = [ type: "image/png", name: "valid file created from props.png", valid: false, + errors: ["File is too big", "File type is not allowed"] }, { id: "fileId-3", @@ -28,7 +29,7 @@ const DemoFileMosaicValidation = () => { return ( <> {sampleFilesProps.map((extFile) => ( - <FileMosaic key={extFile.id} {...extFile} alwaysActive info preview /> + <FileMosaic key={extFile.id} {...extFile} info /> ))} </> ); diff --git a/src/components/show-demo-code/ShowDemoCode.tsx b/src/components/show-demo-code/ShowDemoCode.tsx index 6920473eba486864aff560b7167a20d3ca56a060..64494d98bc7968bb5b242ef32c69fd8fde90f32d 100644 --- a/src/components/show-demo-code/ShowDemoCode.tsx +++ b/src/components/show-demo-code/ShowDemoCode.tsx @@ -13,22 +13,24 @@ interface ShowDemoCodeProps { codeSplittedTS?: string; codeCompleteJS?: string; codeCompleteTS?: string; - splittedOnly?:boolean; + splittedOnly?: boolean; } -const ShowDemoCode: React.FC<ShowDemoCodeProps> = (props: ShowDemoCodeProps) => { +const ShowDemoCode: React.FC<ShowDemoCodeProps> = ( + props: ShowDemoCodeProps +) => { const { codeSandboxJS = "https://codesandbox.io/s/dropzone-ui-basic-3j01v", codeSandboxTS = "https://codesandbox.io/s/dropzone-ui-basic-3j01v", - codeCompleteJS, - codeCompleteTS, - codeSplittedJS, - codeSplittedTS, - splittedOnly=false + codeCompleteJS = "", + codeCompleteTS = "", + codeSplittedJS = "", + codeSplittedTS = "", + splittedOnly = false, } = props; const [showComplete, setShowComplete] = React.useState(false); const [showJS, setShowJS] = React.useState(true); - const code = showComplete + const code: string = showComplete ? showJS ? codeCompleteJS : codeCompleteTS @@ -38,67 +40,83 @@ const ShowDemoCode: React.FC<ShowDemoCodeProps> = (props: ShowDemoCodeProps) => return ( <React.Fragment> - {!splittedOnly && <Stack - direction={"row"} - justifyContent="space-between" - style={{ marginTop: "20px" }} - > - <Stack direction={"row"} justifyContent="flex-start"> - <ButtonGroup variant="outlined" aria-label="outlined button group"> - <Button - size="small" - style={showJS ? { backgroundColor: "rgba(4, 35, 84, 0.09)" } : {}} - //startIcon={} - onClick={() => setShowJS(true)} - > - <JSIcon /> - </Button> - <Button - size="small" - style={ - !showJS ? { backgroundColor: "rgba(4, 35, 84, 0.09)" } : {} - } - // endIcon={} - onClick={() => setShowJS(false)} - > - <TSIcon /> - </Button> - </ButtonGroup> - </Stack> + {!splittedOnly && ( + <Stack + direction={"row"} + justifyContent="space-between" + style={{ margin: "20px 0" }} + > + <Stack direction={"row"} justifyContent="flex-start"> + {code.length > 0 && ( + <ButtonGroup + variant="outlined" + aria-label="outlined button group" + > + <Button + size="small" + style={ + showJS ? { backgroundColor: "rgba(4, 35, 84, 0.09)" } : {} + } + //startIcon={} + onClick={() => setShowJS(true)} + > + <JSIcon /> + </Button> + <Button + size="small" + style={ + !showJS ? { backgroundColor: "rgba(4, 35, 84, 0.09)" } : {} + } + // endIcon={} + onClick={() => setShowJS(false)} + > + <TSIcon /> + </Button> + </ButtonGroup> + )} + </Stack> - <Stack direction={"row"} justifyContent="flex-end"> - <Tooltip title={showComplete ? "Hide full code" : "Show full code"}> - <IconButton - style={{ borderRadius: "50%", border: "0.5px solid #eaeef3" }} - onClick={() => setShowComplete((showComplete) => !showComplete)} - //color="secondary" - aria-label="upload picture" - component="label" - > - <CodeIcon /* htmlColor="white" */ /> - </IconButton> - </Tooltip> - <Tooltip title={"Edit in CodeSandBox"}> - <IconButton - style={{ borderRadius: "50%", border: "0.5px solid #eaeef3" }} - onClick={() => { - window?.open(showJS ? codeSandboxJS : codeSandboxTS, "_blank"); - }} - //color="secondary" - aria-label="upload picture" - component="label" - > - <ViewInArIcon /* htmlColor="white" */ /> - </IconButton> - </Tooltip> + <Stack direction={"row"} justifyContent="flex-end" spacing={1}> + <Tooltip title={showComplete ? "Hide full code" : "Show full code"}> + <IconButton + style={{ borderRadius: "50%", border: "0.5px solid #eaeef3" }} + onClick={() => setShowComplete((showComplete) => !showComplete)} + //color="secondary" + aria-label="upload picture" + component="label" + > + <CodeIcon /* htmlColor="white" */ /> + </IconButton> + </Tooltip> + <Tooltip title={"Edit in CodeSandBox"}> + <IconButton + style={{ borderRadius: "50%", border: "0.5px solid #eaeef3" }} + onClick={() => { + window?.open( + showJS ? codeSandboxJS : codeSandboxTS, + "_blank" + ); + }} + //color="secondary" + aria-label="upload picture" + component="label" + > + <ViewInArIcon /* htmlColor="white" */ /> + </IconButton> + </Tooltip> + </Stack> </Stack> - </Stack>} + )} <Highlighter onCopyToClipboard={(code_) => { console.log("code copied to clipboard: "); console.log(code_); }} - style={{ margin: "20px 0" }} + style={{ + margin: "20px 0", + fontSize:"15px", + lineHeight:"", + }} > {code} </Highlighter> diff --git a/src/files-ui/components/file-mosaic/components/file-mosaic/FileMosaic.tsx b/src/files-ui/components/file-mosaic/components/file-mosaic/FileMosaic.tsx index 841fa9693fd214112f5035ac427dd4ea39026b18..0ce316027b59cd38e516a3185340df3c0ffd7b0c 100644 --- a/src/files-ui/components/file-mosaic/components/file-mosaic/FileMosaic.tsx +++ b/src/files-ui/components/file-mosaic/components/file-mosaic/FileMosaic.tsx @@ -41,9 +41,9 @@ const FileMosaic: React.FC<FileMosaicProps> = (props: FileMosaicProps) => { backgroundBlurImage = true, darkMode, - alwaysActive, + alwaysActive = true, - resultOnTooltip, + resultOnTooltip = true, downloadUrl, diff --git a/src/files-ui/hooks/index.ts b/src/files-ui/hooks/index.ts index f3cc8bea4866823871c61ccd094764fa0a9c8c6d..2125e76a07cf23b6ef24b3f94fed4b7e2f0c91f4 100644 --- a/src/files-ui/hooks/index.ts +++ b/src/files-ui/hooks/index.ts @@ -1,2 +1,5 @@ import {useDropzoneValidation} from "./useDropzoneValidation"; -export {useDropzoneValidation}; \ No newline at end of file +export {useDropzoneValidation}; + + +export {useFakeProgress} from "./useFakeProgress"; \ No newline at end of file diff --git a/src/files-ui/hooks/useFakeProgress.ts b/src/files-ui/hooks/useFakeProgress.ts new file mode 100644 index 0000000000000000000000000000000000000000..9660e290fa3ad8fbbbcf9c3c81dc348b4d840baf --- /dev/null +++ b/src/files-ui/hooks/useFakeProgress.ts @@ -0,0 +1,38 @@ +import * as React from "react"; +import { getRandomInt } from "../core"; + +export const useFakeProgress = (time = 1500) => { + const [progress, setProgress] = React.useState(28); + + React.useEffect(() => { + + const updateProgress = (currProgress: number): number => { + if (currProgress === 100) { + return 0; + } + const offset = getRandomInt(5, 24); + + const newProgress = currProgress + offset; + if (newProgress > 100) { + return 100; + } else { + return newProgress; + } + }; + + const _myInterval = setInterval(() => { + setProgress((_progress) => updateProgress(_progress)); + }, time); + console.log("useFakeProgress SET interval", _myInterval); + + return () => { + console.log("useFakeProgress CLEAR interval", _myInterval); + clearInterval(_myInterval as NodeJS.Timer); + }; + // eslint-disable-next-line + }, []); + + return progress; +} + + diff --git a/src/files-ui/index.ts b/src/files-ui/index.ts index bcd99d84d18e9d4bcb262ca2f3bfab40a7d88f3f..2fa22c1948c5632f693cee686783bfc5be82aebe 100644 --- a/src/files-ui/index.ts +++ b/src/files-ui/index.ts @@ -7,18 +7,20 @@ export * from "./components/avatar/Avatar"; export { FileItem } from "./components"; export * from "./components"; +export { default as FileMosaic } from "./components/file-mosaic/components/file-mosaic/FileMosaic"; +export * from "./components/file-mosaic/components/file-mosaic/FileMosaic"; -export { FileMosaic } from "./components/file-mosaic"; -export * from "./components/file-mosaic"; +export { default as FullScreen } from "./components/previews/FullScreen/FullScreen"; +export * from "./components/previews/FullScreen/FullScreen"; +export { default as ImagePreview } from "./components/previews/ImagePreview/ImagePreview"; +export * from "./components/previews/ImagePreview/ImagePreview"; +export { default as VideoPreview } from "./components/previews/VideoPreview/VideoPreview"; +export * from "./components/previews/VideoPreview/VideoPreview"; -export { FullScreen } from "./components/previews"; -export * from "./components/previews"; +export { useFakeProgress } from "./hooks"; +export {createListOfMultiTypeFile} from "./core"; -export { ImagePreview } from "./components/previews"; -export * from "./components/previews"; - -export { VideoPreview } from "./components/previews"; -export * from "./components/previews"; \ No newline at end of file +export type { ExtFile, ExtFileInstance, ExtFileListMap, ExtFileManager, UPLOADSTATUS, Localization } from "./core"; \ No newline at end of file diff --git a/src/index.css b/src/index.css index 7a599d28313d4affd7b90ecbfb4357acd45587a5..0c7087f9e0f8d669b0967e33b449d123267eb060 100644 --- a/src/index.css +++ b/src/index.css @@ -12,6 +12,10 @@ code { monospace; } - a { +a { color: rgb(0, 121, 244); -} \ No newline at end of file +} + +section { + scroll-margin-top: 64px; +} \ No newline at end of file diff --git a/src/pages/demo/FileMosaicDemoPage.jsx b/src/pages/demo/FileMosaicDemoPage.jsx index c1689c9bb2c0d6b535c39ee81839d56a9bb7cc3b..d3a54f2913477d4e2a50890436aadfa231870e6c 100644 --- a/src/pages/demo/FileMosaicDemoPage.jsx +++ b/src/pages/demo/FileMosaicDemoPage.jsx @@ -1,6 +1,5 @@ import Alert from "@mui/material/Alert"; import Paper from "@mui/material/Paper"; -import Stack from "@mui/material/Stack"; import AlertTitle from "@mui/material/AlertTitle"; import * as React from "react"; import CodeHighlight from "../../components/codeHighlight/CodeHighlight"; @@ -23,6 +22,11 @@ import CodeJSFileMosaicValidation from "../../components/demo-components/filemos import DemoFileMosaicValidation from "../../components/demo-components/filemosaic-demo/DemoFileMosaicValidation"; import CodeJSFileMosaicUploadStatus from "../../components/demo-components/filemosaic-demo/CodeJSFileMosaicUploadStatus"; import DemoFileMosaicUploadStatus from "../../components/demo-components/filemosaic-demo/DemoFileMosaicUploadStatus"; +import DemoFileMosaicLocalization from "../../components/demo-components/filemosaic-demo/DemoFileMosaicLocalization"; +import CodeJSFileMosaicLocalization from "../../components/demo-components/filemosaic-demo/CodeJSFileMosaicLocalization"; +import DemoFileMosaicDarkMode from "../../components/demo-components/filemosaic-demo/DemoFileMosaicDarkMode"; +import CodeJSFileMosaicDarkMode from "../../components/demo-components/filemosaic-demo/CodeJSFileMosaicDarkMode"; +import DemoFileMosaicFileIcons from "../../components/demo-components/filemosaic-demo/DemoFileMosaicFileIcons"; const FileMosaicDemoPage = (props) => { return ( @@ -32,7 +36,7 @@ const FileMosaicDemoPage = (props) => { <MainParagraph> File mosaics are compact elements that represent a file in the UI. They can be used for just showing general info of the file, or either - allow the user to interact with them. + to allow the user to interact with them. </MainParagraph> <DescParagraph> This widget allow users to see information of{" "} @@ -40,21 +44,25 @@ const FileMosaicDemoPage = (props) => { </DescParagraph> <Alert severity="info"> While included here as a standalone component, the most common use - will be as a result of the "onChange" event of {"<Dropzone/>"} or{" "} - {"<InputButton/>"} components, so some of the behavior demonstrated - here is not shown in context.{" "} + will be to display the result of the "onChange" event of{" "} + <CodeHighlight>{"<Dropzone/>"}</CodeHighlight> or{" "} + <CodeHighlight>{"<InputButton/>"}</CodeHighlight> components, so some + of the behavior demonstrated here is not totally shown in context.{" "} </Alert> <section id="basic-filemosaic"> <SubTitle content="Basic FileMosaic" /> <DescParagraph> - The <CodeHighlight>FileMosaic</CodeHighlight> supports displaying - information from a{" "} + The <CodeHighlight>FileMosaic</CodeHighlight> component supports + displaying information from a{" "} <TypeHighlight> <AnchorToTab href="https://developer.mozilla.org/en-US/docs/Web/API/File"> File </AnchorToTab> </TypeHighlight>{" "} - object or from individual props. + object or from given props. + <br /> + Also, the <TypeHighlight>onDelete</TypeHighlight> prop is used to + remove the file selection. </DescParagraph> <DemoContainerFileMosaic> @@ -71,6 +79,19 @@ const FileMosaicDemoPage = (props) => { information of this component check out the{" "} <a href="/components/fileinputbutton">FileInputButton</a> page. </Alert> + <br /> + <Alert severity="info"> + <AlertTitle> ExtFile </AlertTitle> + {/* This is an info alert — <strong>check it out!</strong> + */} + <strong>ExtFile type </strong> + is explicity used in the + <strong> Typescript</strong> example and is implicity used in the{" "} + <strong>Javascript</strong> example for handling the metadata that + makes possible the information exchange between components. For + further information about this data type check out the{" "} + <a href="/types#ext-file">ExtFile-API. </a> + </Alert> </section> <section id="image-preview"> @@ -78,9 +99,15 @@ const FileMosaicDemoPage = (props) => { <DescParagraph> By setting the <CodeHighlight>preview</CodeHighlight> prop to{" "} <TypeHighlight>true</TypeHighlight> the component will show an image - preview by taking the <CodeHighlight>imageUrl</CodeHighlight> - prop or by reading the <TypeHighlight>File</TypeHighlight> object if - given. + preview instead of a file icon. + <br /> + To acomplish this task this component will take the{" "} + <CodeHighlight>imageUrl</CodeHighlight> + prop or will read the <TypeHighlight>File</TypeHighlight> object if + given and if it is an image. + <br /> + Finally, the <TypeHighlight>info</TypeHighlight> prop is used to + show the complete information of the file. </DescParagraph> <DemoContainerFileMosaic> @@ -97,9 +124,10 @@ const FileMosaicDemoPage = (props) => { On the other side, for displaying an image preview as a result of reading an image File it is necesary to set the{" "} <CodeHighlight>{`preview`}</CodeHighlight> prop, otherwise a default - image preview will be shown. + image preview will be shown in order to save memory. </Alert> </section> + <section id="validation"> <SubTitle content="Validation" /> <DescParagraph> @@ -114,6 +142,24 @@ const FileMosaicDemoPage = (props) => { </DemoContainerFileMosaic> <CodeJSFileMosaicValidation /> + <Alert severity="info"> + Typically, <CodeHighlight>{"<Dropzone/>"}</CodeHighlight> or{" "} + <CodeHighlight>{"<FileInputButton/>"}</CodeHighlight> components set + this prop when validating the input from a given criteria. You can + see the behaviour mentioned in the following demos: + <ul> + <li> + <AnchorToTab href="/components/dropzone#validation"> + Dropzone validation + </AnchorToTab> + </li> + <li> + <AnchorToTab href="/components/fileinputbutton#validation"> + FileInputButton validation + </AnchorToTab> + </li> + </ul> + </Alert> </section> <section id="uploading"> @@ -126,7 +172,7 @@ const FileMosaicDemoPage = (props) => { <TypeHighlight>"error"</TypeHighlight> or{" "} <TypeHighlight>"success"</TypeHighlight>. Also the{" "} <CodeHighlight>uploadMessage</CodeHighlight> prop is used for - displaying the error or success message and the{" "} + displaying the error or success message. Finally, the{" "} <CodeHighlight>progress</CodeHighlight> prop can be used to show the current progress of the upload process. <br /> @@ -149,6 +195,139 @@ const FileMosaicDemoPage = (props) => { </Paper> <CodeJSFileMosaicUploadStatus /> + + <Alert severity="info"> + As you can see, you have full control of the FileMosaic upload + props. You can take advantage of them to ake your own upload + function and show the user the progress. + <br /> On the other hand, you can also leverage the capability of{" "} + <CodeHighlight>{"<Dropzone/>"}</CodeHighlight> and{" "} + <CodeHighlight>{"<FileInputButton/>"}</CodeHighlight> components + since they also manage the{" "} + <TypeHighlight>{"uploadStatus"}</TypeHighlight> + prop for you when upload is enabled. You can see the behaviour + mentioned in the following demos: + <ul> + <li> + <AnchorToTab href="/components/dropzone#uploading"> + Dropzone upload + </AnchorToTab> + </li> + <li> + <AnchorToTab href="/components/fileinputbutton#uploading"> + FileInputButton upload + </AnchorToTab> + </li> + </ul> + </Alert> + </section> + <section id="dark-mode"> + <SubTitle content="Dark mode" /> + <DescParagraph> + The <CodeHighlight>FileMosaic</CodeHighlight> component supports + dark mode by setting the prop{" "} + <TypeHighlight>darkMode</TypeHighlight> to{" "} + <TypeHighlight>true</TypeHighlight>. + </DescParagraph> + + <Paper + variant="outlined" + style={{ + //padding: "25px", + display: "flex", + alignItems: "center", + justifyContent: "center", + width: "100%", + }} + > + <DemoFileMosaicDarkMode /> + </Paper> + + <CodeJSFileMosaicDarkMode /> + </section> + <section id="localization"> + <SubTitle content="Localization" /> + <DescParagraph> + The <CodeHighlight>FileMosaic</CodeHighlight> component has + multilanguage support. You can change the language in wich labels + are displayed by setting the{" "} + <CodeHighlight>{"localization"}</CodeHighlight> prop. So far only + the following languages are supported: + <ul> + {[ + "English", + "Spanish", + "French", + "Italian", + "Portuguese", + "Russian", + "Chinnese (simplified)", + "Chinnese (traditional)", + ].map((x) => ( + <li> + <TypeHighlight>{x}</TypeHighlight> + </li> + ))} + </ul> + </DescParagraph> + + <Paper + variant="outlined" + style={{ + padding: "25px", + display: "flex", + alignItems: "center", + justifyContent: "center", + flexDirection: "column", + gap: "20px", + }} + > + <DemoFileMosaicLocalization /> + </Paper> + <CodeJSFileMosaicLocalization /> + </section> + + <section id="file-icon"> + <SubTitle content="File Icons (extensive list)" /> + <DescParagraph> + The <CodeHighlight>FileMosaic</CodeHighlight> component supports + several file types to properly set a file icon. The complete list of + file icons is the following: + </DescParagraph> + <Paper + variant="outlined" + style={{ + padding: "25px 0", + display: "flex", + alignItems: "center", + justifyContent: "center", + //flexDirection: "column", + gap: "10px", + flexWrap: "wrap", + }} + > + <DemoFileMosaicFileIcons /> + </Paper> + </section> + + <section id="api"> + <SubTitle content="API" /> + <DescParagraph> + See the documentation below for a complete reference to all of the + props available to the components mentioned here. + </DescParagraph> + <ul> + <li> + <AnchorToTab href="/api/filemosaic"> + {"<FileMosaic/>"} + </AnchorToTab> + </li> + <li> + <AnchorToTab href="/api/fileinputbuttom"> + {"<FileInputButton/>"} + </AnchorToTab> + </li> + </ul> </section> </MainContentContainer> <RightMenuContainer> @@ -179,29 +358,19 @@ const rightMenuItems = [ label: "Uploading", referTo: "/components/filemosaic#uploading", }, + { + id: 8, + label: "Dark mode", + referTo: "/components/filemosaic#dark-mode", + }, { id: 4, label: "Localization", referTo: "/components/filemosaic#localization", }, { - id: 5, - label: "Previews", - referTo: "/components/filemosaic#previews", - }, - { - id: 6, - label: "Actions", - referTo: "/components/filemosaic#actions", - }, - { - id: 7, - label: "Default previews", - referTo: "/components/filemosaic#default-previews", - }, - { - id: 8, - label: "Dark mode", - referTo: "/components/filemosaic#dark-mode", + id: 9, + label: "File Icons", + referTo: "/components/filemosaic#file-icon", }, ];