{"version":3,"file":"Dropzone.cjs","names":[],"sources":["../../../src/components/Dropzone/Dropzone.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count, function-lines — accept, multiple and maxSize are\n * validation the component must apply before it can call onDrop or onReject, and\n * drag state, keyboard activation and the hidden input all live in the body because\n * they resolve to the same file list.\n */\nimport { useRef, useState } from \"react\";\nimport type { DragEvent, KeyboardEvent, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./Dropzone.module.css\";\n\n/** Props for {@link Dropzone}. */\nexport interface DropzoneProps {\n    /** Called with the accepted files after a drop or file-dialog selection. */\n    onDrop: (files: File[]) => void;\n    /** `accept` attribute forwarded to the hidden file input. */\n    accept?: string;\n    /** Allow selecting/dropping multiple files. Default `true`. */\n    multiple?: boolean;\n    /** Disable interaction. */\n    disabled?: boolean;\n    /** Maximum file size in bytes; larger files are filtered out. */\n    maxSize?: number;\n    /** Called with files rejected by `maxSize`. */\n    onReject?: (files: File[]) => void;\n    /** Custom inner content. Falls back to a default prompt. */\n    children?: ReactNode;\n    /** Extra class applied to the drop area. */\n    className?: string;\n}\n\n/**\n * Drag-and-drop file area with a hidden file input. Clickable and keyboard\n * focusable; filters by `maxSize` before calling `onDrop`.\n *\n * @example\n * <Dropzone accept=\"image/*\" maxSize={5 * 1024 * 1024} onDrop={setFiles}>\n *     Solte imagens aqui ou clique para selecionar\n * </Dropzone>\n */\nexport function Dropzone({\n    onDrop,\n    accept,\n    multiple = true,\n    disabled = false,\n    maxSize,\n    onReject,\n    children,\n    className,\n}: DropzoneProps) {\n    const inputRef = useRef<HTMLInputElement>(null);\n    const [isDragging, setIsDragging] = useState(false);\n\n    const handleFiles = (fileList: FileList | null): void => {\n        if (!fileList || fileList.length === 0) return;\n        const all = Array.from(fileList);\n        const limited = multiple ? all : all.slice(0, 1);\n\n        if (maxSize === undefined) {\n            onDrop(limited);\n            return;\n        }\n\n        const accepted: File[] = [];\n        const rejected: File[] = [];\n        for (const file of limited) {\n            if (file.size > maxSize) rejected.push(file);\n            else accepted.push(file);\n        }\n        if (rejected.length > 0) onReject?.(rejected);\n        if (accepted.length > 0) onDrop(accepted);\n    };\n\n    const openDialog = (): void => {\n        if (disabled) return;\n        inputRef.current?.click();\n    };\n\n    const handleDragEnter = (event: DragEvent<HTMLDivElement>): void => {\n        event.preventDefault();\n        if (disabled) return;\n        setIsDragging(true);\n    };\n\n    const handleDragOver = (event: DragEvent<HTMLDivElement>): void => {\n        event.preventDefault();\n    };\n\n    const handleDragLeave = (event: DragEvent<HTMLDivElement>): void => {\n        event.preventDefault();\n        setIsDragging(false);\n    };\n\n    const handleDrop = (event: DragEvent<HTMLDivElement>): void => {\n        event.preventDefault();\n        setIsDragging(false);\n        if (disabled) return;\n        handleFiles(event.dataTransfer.files);\n    };\n\n    const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n        if (event.key === \"Enter\" || event.key === \" \") {\n            event.preventDefault();\n            openDialog();\n        }\n    };\n\n    return (\n        <div\n            role=\"button\"\n            tabIndex={disabled ? -1 : 0}\n            aria-disabled={disabled || undefined}\n            className={cn(\n                styles.zone,\n                isDragging && styles.dragging,\n                disabled && styles.disabled,\n                className,\n            )}\n            onClick={openDialog}\n            onKeyDown={handleKeyDown}\n            onDragEnter={handleDragEnter}\n            onDragOver={handleDragOver}\n            onDragLeave={handleDragLeave}\n            onDrop={handleDrop}\n        >\n            <input\n                ref={inputRef}\n                type=\"file\"\n                className={styles.input}\n                accept={accept}\n                multiple={multiple}\n                disabled={disabled}\n                onChange={(event) => {\n                    handleFiles(event.target.files);\n                    event.target.value = \"\";\n                }}\n            />\n            {children ?? (\n                <span className={styles.prompt}>\n                    Arraste arquivos aqui ou clique para selecionar\n                </span>\n            )}\n        </div>\n    );\n}\n"],"mappings":"+HAwCA,SAAgB,EAAS,CACrB,SACA,SACA,WAAW,GACX,WAAW,GACX,UACA,WACA,WACA,aACc,CACd,IAAM,GAAA,EAAW,EAAA,OAAA,CAAyB,IAAI,EACxC,CAAC,EAAY,IAAA,EAAiB,EAAA,SAAA,CAAS,EAAK,EAE5C,EAAe,GAAoC,CACrD,GAAI,CAAC,GAAY,EAAS,SAAW,EAAG,OACxC,IAAM,EAAM,MAAM,KAAK,CAAQ,EACzB,EAAU,EAAW,EAAM,EAAI,MAAM,EAAG,CAAC,EAE/C,GAAI,IAAY,IAAA,GAAW,CACvB,EAAO,CAAO,EACd,MACJ,CAEA,IAAM,EAAmB,CAAC,EACpB,EAAmB,CAAC,EAC1B,IAAK,IAAM,KAAQ,EACX,EAAK,KAAO,EAAS,EAAS,KAAK,CAAI,EACtC,EAAS,KAAK,CAAI,EAEvB,EAAS,OAAS,GAAG,IAAW,CAAQ,EACxC,EAAS,OAAS,GAAG,EAAO,CAAQ,CAC5C,EAEM,MAAyB,CACvB,GACJ,EAAS,SAAS,MAAM,CAC5B,EA+BA,OACI,EAAA,EAAA,KAAA,CAAC,MAAD,CACI,KAAK,SACL,SAAU,EAAW,GAAK,EAC1B,gBAAe,GAAY,IAAA,GAC3B,UAAW,EAAA,GACP,EAAA,QAAO,KACP,GAAc,EAAA,QAAO,SACrB,GAAY,EAAA,QAAO,SACnB,CACJ,EACA,QAAS,EACT,UAnBe,GAA+C,EAC9D,EAAM,MAAQ,SAAW,EAAM,MAAQ,OACvC,EAAM,eAAe,EACrB,EAAW,EAEnB,EAeQ,YA1CiB,GAA2C,CAChE,EAAM,eAAe,EACjB,IACJ,EAAc,EAAI,CACtB,EAuCQ,WArCgB,GAA2C,CAC/D,EAAM,eAAe,CACzB,EAoCQ,YAlCiB,GAA2C,CAChE,EAAM,eAAe,EACrB,EAAc,EAAK,CACvB,EAgCQ,OA9BY,GAA2C,CAC3D,EAAM,eAAe,EACrB,EAAc,EAAK,EACf,IACJ,EAAY,EAAM,aAAa,KAAK,CACxC,EAUI,SAAA,EAiBI,EAAA,EAAA,IAAA,CAAC,QAAD,CACI,IAAK,EACL,KAAK,OACL,UAAW,EAAA,QAAO,MACV,SACE,WACA,WACV,SAAW,GAAU,CACjB,EAAY,EAAM,OAAO,KAAK,EAC9B,EAAM,OAAO,MAAQ,EACzB,CACH,CAAA,EACA,IACG,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,OAAQ,SAAA,iDAE1B,CAAA,CAET,GAEb"}