Skip to content

Commit

Permalink
Merge pull request #28 from FiligranHQ/issue/file-input-add-type-control
Browse files Browse the repository at this point in the history
Issue/file input add type control
  • Loading branch information
hervyt authored Oct 21, 2024
2 parents 8fe61f6 + 783b367 commit 42b4705
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 68 deletions.
91 changes: 27 additions & 64 deletions packages/filigran-ui/src/components/clients/file-input.tsx
Original file line number Diff line number Diff line change
@@ -1,113 +1,76 @@
'use client'
import {AddNotesIcon, ReadMoreIcon, TaskIcon} from 'filigran-icon'
import {useState} from 'react'
import {cn, fixedForwardRef} from '../../lib/utils'
import {fixedForwardRef} from '../../lib/utils'
import {Button} from '../servers'

const FileStatusDisplay = ({
icon: Icon,
text,
}: {
icon: React.ElementType
text: string
}) => (
<div className="flex flex-col items-center justify-center pointer-events-none text-gray-700 dark:text-gray-300">
<Icon className="h-10 w-10" />
<p className="mt-s text-sm flex items-center justify-center text-center">
{text}
</p>
</div>
)

interface FileInputProps {
interface FileInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
texts?: Partial<InputText>
className?: string | undefined
allowedTypes: string
handleFileChange: (file: FileList | null) => void
}

interface InputText {
dragActive: string
dragUnactive: string
fileOk: string
selectFile: string
noFile: string
}

const defaultTexts: InputText = {
dragActive: 'Drop the file here',
dragUnactive: 'Select a file',
fileOk: 'Choosen file',
selectFile: 'Select a file',
noFile: 'No file selected',
}

function GenericFileInput(
{texts, className, handleFileChange, ...props}: FileInputProps,
{texts, allowedTypes, className, handleFileChange, ...props}: FileInputProps,
ref?: any
) {
const [isDragActive, setIsDragActive] = useState<boolean>(false)
const [isFileSelected, setIsFileSelected] = useState<boolean>(false)

const [fileSelected, setFileSelected] = useState<File>(null)
const textForComp: InputText = {...defaultTexts, ...texts}

const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault()
setIsDragActive(true)
}

const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault()
e.stopPropagation()
setIsDragActive(true)
}

const handleDragLeave = () => setIsDragActive(false)

const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault()
setIsDragActive(false)
setIsFileSelected(true)
const hasExtension = e.dataTransfer.files[0].name.includes('.')

if (
!allowedTypes?.includes(e.dataTransfer.files[0].type) ||
!hasExtension
) {
return
}

setFileSelected(e.dataTransfer.files[0])
handleFileChange(e.dataTransfer.files)
}

const fileClicked = (e: React.ChangeEvent<HTMLInputElement>) => {
setIsFileSelected(true)
setFileSelected(e.target.files[0])
handleFileChange(e.target.files)
}

const renderIcon = () => {
if (isFileSelected) {
return TaskIcon
}
return isDragActive ? ReadMoreIcon : AddNotesIcon
}

const renderText = (): string => {
if (isFileSelected) {
return textForComp.fileOk
}
return isDragActive ? textForComp.dragActive : textForComp.dragUnactive
}

return (
<div
className={cn(
'relative h-48 w-48 border-2 border-dashed rounded-lg flex items-center justify-center',
className ?? '',
isDragActive
? 'border-blue bg-blue-100 dark:bg-darkblue-800'
: 'border-gray-400 bg-gray-100 dark:bg-darkblue-900'
)}
onDragEnter={handleDragEnter}
onDragLeave={handleDragLeave}
onDragOver={handleDragOver}
onDrop={handleDrop}>
<input
accept={allowedTypes}
type={'file'}
className="opacity-0 absolute inset-0 z-10 w-full h-full cursor-pointer"
className="hidden"
onChange={fileClicked}
ref={ref}
{...props}
/>
<FileStatusDisplay
icon={renderIcon()}
text={renderText()}
/>
<Button onClick={() => ref.current && ref.current.click()}>
{textForComp?.selectFile}
</Button>{' '}
{fileSelected?.name ?? textForComp.noFile}
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import React, {useRef, useState} from 'react'
import {FileInput} from 'filigran-ui/clients'
const ExampleFileInput = () => {
const fileInputRef = useRef(null)
const [fileName, setFileName] = useState<string | null>(null)

const handleFileChange = (files: FileList | null) => {
if (files && files.length > 0) {
console.log('Fichier sélectionné :', files[0])
setFileName(files[0].name)
}
}

return (
<div className="my-8">
<FileInput
allowedTypes={
'image/*,application/pdf,video/*,application/msword,application/zip,application/json'
}
handleFileChange={handleFileChange}
ref={fileInputRef}
texts={{
dragUnactive: 'Select a fileX',
fileOk: fileName ?? '',
selectFile: 'Select a fileX',
}}
/>
</div>
Expand Down

0 comments on commit 42b4705

Please sign in to comment.