{"version":3,"sources":["../src/components/ImageUpload/ImageUpload.tsx"],"sourcesContent":["import type React from 'react';\nimport { useRef, useState } from 'react';\nimport { ImageIcon } from '@phosphor-icons/react/dist/csr/Image';\nimport { PaperclipIcon } from '@phosphor-icons/react/dist/csr/Paperclip';\nimport { XIcon } from '@phosphor-icons/react/dist/csr/X';\nimport Text from '../Text/Text';\nimport Button from '../Button/Button';\nimport { cn } from '../../utils/utils';\n\nexport interface ImageUploadProps {\n  /** File currently selected */\n  selectedFile?: File | null;\n  /** Upload progress (0-100). If not provided, progress bar won't show */\n  uploadProgress?: number;\n  /** Show progress bar even if uploadProgress is 100 */\n  showProgress?: boolean;\n  /** Callback when a file is selected */\n  onFileSelect?: (file: File) => void;\n  /** Callback when file is removed */\n  onRemoveFile?: () => void;\n  /** Custom button text when no file is selected */\n  buttonText?: string;\n  /** Custom button icon when no file is selected */\n  buttonIcon?: React.ReactNode;\n  /** Accept specific file types (default: \"image/*\") */\n  accept?: string;\n  /** Disabled state */\n  disabled?: boolean;\n  /** Custom class name */\n  className?: string;\n  /** Max file size in bytes */\n  maxSize?: number;\n  /** Callback when file size exceeds maxSize */\n  onSizeError?: (file: File, maxSize: number) => void;\n  /** Callback when invalid file type is selected */\n  onTypeError?: (file: File) => void;\n  /** Variant of the upload button */\n  variant?: 'default' | 'compact';\n}\n\nexport default function ImageUpload({\n  selectedFile,\n  onFileSelect,\n  onRemoveFile,\n  buttonText = 'Inserir imagem',\n  buttonIcon,\n  accept = 'image/*',\n  disabled = false,\n  className,\n  maxSize,\n  onSizeError,\n  onTypeError,\n  variant = 'default',\n}: Readonly<ImageUploadProps>) {\n  const fileInputRef = useRef<HTMLInputElement>(null);\n  const [internalFile, setInternalFile] = useState<File | null>(null);\n\n  // Use controlled or uncontrolled mode\n  const currentFile = selectedFile ?? internalFile;\n  const hasFile = currentFile !== null;\n\n  const handleButtonClick = () => {\n    if (!disabled) {\n      fileInputRef.current?.click();\n    }\n  };\n\n  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n    const file = event.target.files?.[0];\n\n    if (!file) return;\n\n    // Validate file type\n    const acceptedTypes = accept.split(',').map((type) => type.trim());\n    const isValidType = acceptedTypes.some((type) => {\n      if (type.endsWith('/*')) {\n        const mainType = type.split('/')[0];\n        return file.type.startsWith(mainType + '/');\n      }\n      if (type.startsWith('.')) {\n        return file.name.toLowerCase().endsWith(type.toLowerCase());\n      }\n      return file.type === type;\n    });\n\n    if (!isValidType) {\n      onTypeError?.(file);\n      return;\n    }\n\n    // Validate file size\n    if (maxSize && file.size > maxSize) {\n      onSizeError?.(file, maxSize);\n      return;\n    }\n\n    // Update state\n    if (selectedFile === undefined) {\n      setInternalFile(file);\n    }\n    onFileSelect?.(file);\n\n    // Reset input value to allow selecting the same file again\n    event.target.value = '';\n  };\n\n  const handleRemoveFile = () => {\n    if (!disabled) {\n      if (selectedFile === undefined) {\n        setInternalFile(null);\n      }\n      onRemoveFile?.();\n    }\n  };\n\n  if (variant === 'compact') {\n    return (\n      <div className={cn('inline-flex items-center gap-2', className)}>\n        {hasFile ? (\n          <div className=\"inline-flex items-center gap-2 bg-muted rounded-md px-3 py-1.5\">\n            <PaperclipIcon className=\"h-4 w-4 text-text-800\" />\n            <Text size=\"sm\" weight=\"medium\" className=\"text-text-800\">\n              {currentFile.name}\n            </Text>\n            <button\n              type=\"button\"\n              onClick={handleRemoveFile}\n              disabled={disabled}\n              className=\"hover:opacity-70 disabled:cursor-not-allowed disabled:opacity-50\"\n              aria-label=\"Remover imagem\"\n              title=\"Remover imagem\"\n            >\n              <XIcon className=\"h-3 w-3 text-primary-950\" />\n            </button>\n          </div>\n        ) : (\n          <Button\n            type=\"button\"\n            variant=\"link\"\n            size=\"extra-small\"\n            onClick={handleButtonClick}\n            disabled={disabled}\n          >\n            {buttonIcon || <ImageIcon className=\"h-4 w-4\" />}\n            <span className=\"ml-2\">{buttonText}</span>\n          </Button>\n        )}\n        <input\n          ref={fileInputRef}\n          type=\"file\"\n          accept={accept}\n          className=\"hidden\"\n          onChange={handleFileChange}\n          disabled={disabled}\n        />\n      </div>\n    );\n  }\n\n  return (\n    <div className={cn('space-y-3', className)}>\n      {hasFile ? (\n        <div className=\"space-y-2\">\n          <div className=\"inline-flex items-center gap-2 bg-muted rounded-md px-3 py-2\">\n            <PaperclipIcon className=\"h-4 w-4 text-text-800\" />\n            <Text size=\"sm\" weight=\"medium\" className=\"text-text-800\">\n              {currentFile.name}\n            </Text>\n            <button\n              type=\"button\"\n              onClick={handleRemoveFile}\n              disabled={disabled}\n              className=\"hover:opacity-70 disabled:cursor-not-allowed disabled:opacity-50\"\n              aria-label=\"Remover imagem\"\n              title=\"Remover imagem\"\n            >\n              <XIcon className=\"h-4 w-4 text-primary-950 cursor-pointer\" />\n            </button>\n          </div>\n        </div>\n      ) : (\n        <Button\n          type=\"button\"\n          variant=\"link\"\n          className=\"gap-1.5\"\n          onClick={handleButtonClick}\n          disabled={disabled}\n        >\n          {buttonIcon || <ImageIcon className=\"h-4 w-4\" />}\n          {buttonText}\n        </Button>\n      )}\n      <input\n        ref={fileInputRef}\n        type=\"file\"\n        accept={accept}\n        className=\"hidden\"\n        onChange={handleFileChange}\n        disabled={disabled}\n      />\n    </div>\n  );\n}\n"],"mappings":"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","names":[]}