-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #75 from ruru-m07/feat/component/dropzone
feat(dropzone): add dropzone component and documentation
- Loading branch information
Showing
15 changed files
with
412 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
"use client"; | ||
|
||
import React from "react"; | ||
import { Dropzone, RD } from "ruru-ui/components/dropzone"; | ||
|
||
import { File } from "lucide-react"; | ||
|
||
const AdvanceDropzone = () => { | ||
const [files, setFiles] = React.useState<RD.FileWithPath[]>([]); | ||
|
||
function formatFileSize(bytes: number) { | ||
if (bytes === 0) return "0 Bytes"; | ||
const k = 1024; | ||
const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; | ||
const i = Math.floor(Math.log(bytes) / Math.log(k)); | ||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; | ||
} | ||
|
||
const onDrop = (acceptedFiles: RD.FileWithPath[]) => { | ||
setFiles((p) => [...p, ...acceptedFiles]); | ||
}; | ||
|
||
return ( | ||
<div className="w-full"> | ||
<Dropzone onDrop={onDrop} /> | ||
{files.length > 0 && ( | ||
<section className="my-4"> | ||
<h4 className="scroll-m-20 text-xl font-semibold tracking-tight"> | ||
Files | ||
</h4> | ||
{files.map((file, index) => ( | ||
<div | ||
key={index} | ||
className="space-x-3 w-[100%] border-[1.5px] border-input flex items-center justify-between rounded-md py-3 px-3 my-3" | ||
> | ||
<div className="flex items-center"> | ||
<File size={20} className="text-muted-foreground" /> | ||
<span className="ml-2 text-sm">{file.path}</span> | ||
</div> | ||
<span className="text-muted-foreground text-xs"> | ||
{formatFileSize(file.size)} | ||
</span> | ||
</div> | ||
))} | ||
</section> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default AdvanceDropzone; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
"use client"; | ||
|
||
import React from "react"; | ||
import { Wrapper } from "../wrapper"; | ||
import { Dropzone } from "ruru-ui/components/dropzone"; | ||
|
||
const DropzonePreview = () => { | ||
return ( | ||
<Wrapper className="p-10"> | ||
<Dropzone /> | ||
</Wrapper> | ||
); | ||
}; | ||
|
||
export default DropzonePreview; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
--- | ||
title: Dropzone | ||
description: Dropzone allows the user to drag and drop files to upload. | ||
preview: dropzone | ||
--- | ||
|
||
import { Tab, Tabs } from "fumadocs-ui/components/tabs"; | ||
import { Tabs as Rutabs, Tab as Rutab } from "ruru-ui/components/tabs"; | ||
import { Dropzone } from "ruru-ui/components/dropzone"; | ||
import AdvanceDropzone from "@/components/preview/dropzone/advanceDropzone"; | ||
|
||
## Installation | ||
|
||
<Rutabs items={["CLI", "Dependencies"]}> | ||
<Rutab value={"CLI"}> | ||
<Tabs items={["npm", "pnpm", "yarn", "bun"]}> | ||
<Tab value={"npm"}> | ||
```bash | ||
npx ruru-ui-cli@latest add dropzone | ||
``` | ||
</Tab> | ||
<Tab value={"pnpm"}> | ||
```bash | ||
pnpm dlx ruru-ui-cli@latest add dropzone | ||
``` | ||
</Tab> | ||
<Tab value={"yarn"}> | ||
```bash | ||
npx ruru-ui-cli@latest add dropzone | ||
``` | ||
</Tab> | ||
<Tab value={"bun"}> | ||
```bash | ||
bunx --bun ruru-ui-cli@latest add dropzone | ||
``` | ||
</Tab> | ||
</Tabs> | ||
|
||
</Rutab> | ||
<Rutab value={"Dependencies"}> | ||
```package-install | ||
npm install ruru-ui@latest | ||
``` | ||
</Rutab> | ||
</Rutabs> | ||
|
||
## Usage | ||
|
||
The `Dropzone` component is used to allow the user to drag and drop files to upload. | ||
This component is a **wrapper** around the [react-dropzone](https://github.com/react-dropzone/react-dropzone) library. | ||
|
||
<Tabs items={["Preview", "Code"]}> | ||
<Tab className={"flex justify-center"} value="Preview" > | ||
<div className="p-4 w-full"> | ||
<Dropzone /> | ||
</div> | ||
</Tab> | ||
<Tab className={"-mt-8"} value="Code"> | ||
```tsx | ||
// [!code word:Dropzone] | ||
import { Dropzone } from "ruru-ui/components/dropzone"; | ||
|
||
export function Demo() { | ||
return <Dropzone onDrop={(acceptedFiles) => console.log(acceptedFiles)} />; | ||
} | ||
``` | ||
</Tab> | ||
</Tabs> | ||
|
||
--- | ||
|
||
### Advanced Example | ||
|
||
In this example, we learn how to handle files using the Dropzone component. | ||
|
||
<Tabs items={["Preview", "Code"]}> | ||
<Tab className={"flex justify-center"} value="Preview" > | ||
<div className="p-4 w-full"> | ||
<AdvanceDropzone className="m-10" /> | ||
</div> | ||
</Tab> | ||
<Tab className={"-mt-8"} value="Code"> | ||
```tsx | ||
"use client"; | ||
|
||
import React from "react"; | ||
import { Dropzone, RD } from "ruru-ui/components/dropzone"; | ||
|
||
import { File } from "lucide-react"; | ||
|
||
const AdvanceDropzone = () => { | ||
const [files, setFiles] = React.useState<RD.FileWithPath[]>([]); | ||
|
||
function formatFileSize(bytes: number) { | ||
if (bytes === 0) return "0 Bytes"; | ||
const k = 1024; | ||
const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; | ||
const i = Math.floor(Math.log(bytes) / Math.log(k)); | ||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; | ||
} | ||
|
||
const onDrop = (acceptedFiles: RD.FileWithPath[]) => { | ||
setFiles((p) => [...p, ...acceptedFiles]); | ||
}; | ||
|
||
return ( | ||
<div className="w-full"> | ||
<Dropzone onDrop={onDrop} /> | ||
{files.length > 0 && ( | ||
<section className="my-4"> | ||
<h4 className="scroll-m-20 text-xl font-semibold tracking-tight"> | ||
Files | ||
</h4> | ||
{files.map((file, index) => ( | ||
<div | ||
key={index} | ||
className="space-x-3 w-[100%] border-[1.5px] border-input flex items-center justify-between rounded-md py-3 px-3 my-3" | ||
> | ||
<div className="flex items-center"> | ||
<File size={20} className="text-muted-foreground" /> | ||
<span className="ml-2 text-sm">{file.path}</span> | ||
</div> | ||
<span className="text-muted-foreground text-xs"> | ||
{formatFileSize(file.size)} | ||
</span> | ||
</div> | ||
))} | ||
</section> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default AdvanceDropzone; | ||
``` | ||
</Tab> | ||
</Tabs> | ||
|
||
## Import | ||
|
||
We are exporting the `RD` component from the `react-dropzone` module. | ||
Here RD is the alias for the `react-dropzone` library. | ||
|
||
```tsx title="dropzone.tsx" | ||
// [!code word:RD] | ||
import * as RD from "react-dropzone"; | ||
export { RD }; | ||
``` | ||
|
||
## Props | ||
|
||
| Name | Type | Default | Description | | ||
| --------- | ------------------------------------------------- | ------- | --------------------------------------------------------- | | ||
| className | string | "" | Optional additional class names for styling the dropzone. | | ||
| props | DropzoneProps & React.RefAttributes\<DropzoneRef> | {} | Props passed to the `react-dropzone` component. | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,14 @@ | ||
const { execSync } = require("child_process"); | ||
|
||
/** @type {import('next-sitemap').IConfig} */ | ||
module.exports = { | ||
siteUrl: process.env.SITE_URL || "https://ruru-ui.vercel.app", | ||
generateRobotsTxt: true, | ||
exclude: ["/api/*"], | ||
transform: async (config, path) => { | ||
const lastmod = await getLastModifiedDate(path); | ||
return { | ||
loc: path, | ||
changefreq: config.changefreq, | ||
priority: config.priority, | ||
lastmod, | ||
alternateRefs: config.alternateRefs ?? [], | ||
}; | ||
}, | ||
}; | ||
|
||
async function getLastModifiedDate(path) { | ||
try { | ||
const timestamp = execSync(`git log -1 --format=%ct ${path}`) | ||
.toString() | ||
.trim(); | ||
return new Date(parseInt(timestamp, 10) * 1000).toISOString(); | ||
} catch (error) { | ||
console.error(`Error getting last modified date for ${path}:`, error); | ||
return new Date().toISOString(); // Fallback to current date | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"name": "dropzone", | ||
"dependencies": ["react-dropzone"], | ||
"files": [ | ||
{ | ||
"name": "dropzone.tsx", | ||
"content": "\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { FilePlusIcon } from \"@radix-ui/react-icons\";\nimport ReactDropzone, { DropzoneProps, DropzoneRef } from \"react-dropzone\";\n\n\nexport const Dropzone = ({\n className,\n ...props\n}: DropzoneProps &\n React.RefAttributes<DropzoneRef> & {\n className?: string;\n }): React.ReactNode => {\n return (\n <>\n {}\n <div\n className={cn(\n \"items-center justify-center w-full p-5 border rounded-md bg-primary-foreground/65\",\n className,\n )}\n >\n {}\n <ReactDropzone {...props}>\n {({ getRootProps, getInputProps, isDragActive }) => (\n <section className=\"flex items-center justify-center h-96\">\n {}\n <div\n className=\"flex items-center justify-center w-full h-full\"\n {...getRootProps()}\n >\n <input {...getInputProps()} />\n {isDragActive ? (\n \n <div className=\"flex items-center justify-center w-full h-full border-2 border-dashed rounded-md\">\n <div className=\"flex flex-col justify-center items-center\">\n <FilePlusIcon\n className=\"mb-3 text-muted-foreground\"\n height={100}\n width={50}\n />\n <span className=\"text-muted-foreground\">\n Drop to Upload file\n </span>\n </div>\n </div>\n ) : (\n \n <div className=\"w-full flex flex-col justify-center items-center\">\n <FilePlusIcon\n className=\"mb-3 text-muted-foreground\"\n height={100}\n width={50}\n />\n <span id=\"dragzone-text\" className=\"text-muted-foreground\">\n Drag files here to add them to your repository\n </span>\n <span className=\"text-muted-foreground\">\n or{\" \"}\n <span className=\"text-blue-500 cursor-pointer hover:underline ml-1\">\n choose your file\n </span>\n </span>\n </div>\n )}\n </div>\n </section>\n )}\n </ReactDropzone>\n </div>\n </>\n );\n};\n\nimport * as RD from \"react-dropzone\";\nexport { RD };\n" | ||
} | ||
], | ||
"type": "components:ui" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.