Skip to content

Commit

Permalink
feat: 🎸 context and preview image
Browse files Browse the repository at this point in the history
  • Loading branch information
julianoalvescode committed Apr 9, 2024
1 parent bd2be94 commit fcea336
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 8 deletions.
25 changes: 23 additions & 2 deletions src/components/Form/FileInput/Control.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
import { ComponentProps } from "react";
"use client";

import { ChangeEvent, ComponentProps } from "react";
import { useFileInput } from "./Root";

export type ControlProps = ComponentProps<"input">;

export function Control(props: ControlProps) {
return <input type="file" className="sr-only" id="photo" {...props} />;
const { id, onFileSelected } = useFileInput();

function handleFilesSelected(event: ChangeEvent<HTMLInputElement>) {
if (!event.target.files?.length) return;

const files = Array.from(event.target.files);

onFileSelected(files);
}

return (
<input
type="file"
className="sr-only"
onChange={handleFilesSelected}
id={id}
{...props}
/>
);
}
31 changes: 28 additions & 3 deletions src/components/Form/FileInput/ImagePreview.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
"use client";

import { User } from "lucide-react";
import { useFileInput } from "./Root";
import { useMemo } from "react";

export function ImagePreview() {
const { files } = useFileInput();

const previewURL = useMemo(() => {
if (files.length === 0) {
return null;
}

return URL.createObjectURL(files[0]);
}, [files]);

if (previewURL === null) {
return (
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-violet-50">
<User className="h-8 w-8 text-violet-500" />
</div>
);
}

return (
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-violet-50">
<User className="h-8 w-8 text-violet-500" />
</div>
// eslint-disable-next-line @next/next/no-img-element
<img
src={previewURL}
alt=""
className="h-16 w-16 rounded-full object-cover"
/>
);
}
29 changes: 27 additions & 2 deletions src/components/Form/FileInput/Root.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
import { ComponentProps } from "react";
"use client";

import {
ComponentProps,
createContext,
useContext,
useId,
useState,
} from "react";

export type RootProps = ComponentProps<"div">;

type FileInputContextType = {
id: string;
files: File[];
onFileSelected: (files: File[]) => void;
};

const FileInputContext = createContext({} as FileInputContextType);

export function Root(props: RootProps) {
return <div {...props} />;
const id = useId();
const [files, setFiles] = useState<File[]>([]);

return (
<FileInputContext.Provider value={{ id, files, onFileSelected: setFiles }}>
<div {...props} />;
</FileInputContext.Provider>
);
}

export const useFileInput = () => useContext(FileInputContext);
7 changes: 6 additions & 1 deletion src/components/Form/FileInput/Trigger.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
"use client";

import { UploadCloud } from "lucide-react";
import { useFileInput } from "./Root";

export function Trigger() {
const { id } = useFileInput();

return (
<label
htmlFor="photo"
htmlFor={id}
className="group flex flex-1 cursor-pointer flex-col items-center gap-3 rounded-lg border border-zinc-300 px-6 py-4 text-center text-zinc-500 shadow-sm hover:border-violet-200 hover:bg-violet-25 hover:text-violet-500"
>
<div className="rounded-full border-6 border-zinc-50 bg-zinc-100 p-2 group-hover:border-violet-50 group-hover:bg-violet-100">
Expand Down

0 comments on commit fcea336

Please sign in to comment.