{"version":3,"sources":["../src/avatar-upload/avatar-upload.tsx"],"names":["cva","React","isImageFile","formatBytes","jsxs","cn","jsx","User","Camera","Loader2","X"],"mappings":"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","file":"chunk-XKFQJNFD.cjs","sourcesContent":["\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Camera, Loader2, Upload, User, X } from \"lucide-react\";\nimport * as React from \"react\";\nimport type { UploadHandler } from \"../lib/types\";\nimport { cn, formatBytes, isImageFile } from \"../lib/utils\";\n\nconst avatarVariants = cva(\n  \"relative rounded-full overflow-hidden bg-muted flex items-center justify-center cursor-pointer transition-all group\",\n  {\n    variants: {\n      size: {\n        sm: \"h-16 w-16\",\n        default: \"h-24 w-24\",\n        lg: \"h-32 w-32\",\n        xl: \"h-40 w-40\",\n      },\n    },\n    defaultVariants: {\n      size: \"default\",\n    },\n  },\n);\n\nconst iconVariants = cva(\"text-muted-foreground\", {\n  variants: {\n    size: {\n      sm: \"h-6 w-6\",\n      default: \"h-8 w-8\",\n      lg: \"h-10 w-10\",\n      xl: \"h-12 w-12\",\n    },\n  },\n  defaultVariants: {\n    size: \"default\",\n  },\n});\n\nconst overlayVariants = cva(\n  \"absolute inset-0 bg-black/60 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity\",\n  {\n    variants: {\n      size: {\n        sm: \"\",\n        default: \"\",\n        lg: \"\",\n        xl: \"\",\n      },\n    },\n    defaultVariants: {\n      size: \"default\",\n    },\n  },\n);\n\nexport interface AvatarUploadProps\n  extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onChange\">,\n    VariantProps<typeof avatarVariants> {\n  /**\n   * Upload handler configuration\n   */\n  handler: UploadHandler;\n  /**\n   * Current avatar URL\n   */\n  value?: string | null;\n  /**\n   * Called when avatar changes\n   */\n  onChange?: (url: string | null) => void;\n  /**\n   * Called when upload completes\n   */\n  onUploadComplete?: (url: string) => void;\n  /**\n   * Maximum file size in bytes\n   * @default 5 * 1024 * 1024 (5MB)\n   */\n  maxSize?: number;\n  /**\n   * Accepted image types\n   * @default [\"image/jpeg\", \"image/png\", \"image/gif\", \"image/webp\"]\n   */\n  accept?: string[];\n  /**\n   * Whether to allow removing the avatar\n   * @default true\n   */\n  allowRemove?: boolean;\n  /**\n   * Disabled state\n   */\n  disabled?: boolean;\n  /**\n   * Fallback initials or name\n   */\n  fallback?: string;\n}\n\ntype UploadState = \"idle\" | \"uploading\" | \"processing\" | \"error\";\n\nexport function AvatarUpload({\n  handler,\n  value,\n  onChange,\n  onUploadComplete,\n  maxSize = 5 * 1024 * 1024,\n  accept = [\"image/jpeg\", \"image/png\", \"image/gif\", \"image/webp\"],\n  allowRemove = true,\n  disabled = false,\n  fallback,\n  size,\n  className,\n  ...props\n}: AvatarUploadProps) {\n  const [uploadState, setUploadState] = React.useState<UploadState>(\"idle\");\n  const [error, setError] = React.useState<string | null>(null);\n  const [previewUrl, setPreviewUrl] = React.useState<string | null>(null);\n  const inputRef = React.useRef<HTMLInputElement>(null);\n\n  // Clean up preview URL on unmount\n  React.useEffect(() => {\n    return () => {\n      if (previewUrl) {\n        URL.revokeObjectURL(previewUrl);\n      }\n    };\n  }, [previewUrl]);\n\n  const handleClick = React.useCallback(() => {\n    if (!disabled && uploadState === \"idle\") {\n      inputRef.current?.click();\n    }\n  }, [disabled, uploadState]);\n\n  const handleRemove = React.useCallback(\n    (e: React.MouseEvent) => {\n      e.stopPropagation();\n      if (previewUrl) {\n        URL.revokeObjectURL(previewUrl);\n        setPreviewUrl(null);\n      }\n      onChange?.(null);\n    },\n    [onChange, previewUrl],\n  );\n\n  const handleFileSelect = React.useCallback(\n    async (e: React.ChangeEvent<HTMLInputElement>) => {\n      const file = e.target.files?.[0];\n      e.target.value = \"\";\n\n      if (!file) return;\n\n      // Validate file type\n      if (!isImageFile(file.type) || !accept.includes(file.type)) {\n        setError(\"Please select a valid image file\");\n        return;\n      }\n\n      // Validate file size\n      if (file.size > maxSize) {\n        setError(`Image must be less than ${formatBytes(maxSize)}`);\n        return;\n      }\n\n      setError(null);\n\n      // Create preview\n      const objectUrl = URL.createObjectURL(file);\n      if (previewUrl) {\n        URL.revokeObjectURL(previewUrl);\n      }\n      setPreviewUrl(objectUrl);\n\n      try {\n        setUploadState(\"uploading\");\n\n        // Get upload URL\n        const { uploadUrl, assetId } = await handler.getUploadUrl(file);\n\n        // Upload file\n        const response = await fetch(uploadUrl, {\n          method: \"PUT\",\n          body: file,\n          headers: {\n            \"Content-Type\": file.type,\n          },\n        });\n\n        if (!response.ok) {\n          throw new Error(\"Upload failed\");\n        }\n\n        setUploadState(\"processing\");\n\n        // Confirm upload\n        let finalUrl = objectUrl;\n        if (handler.onUploadComplete && assetId) {\n          const result = await handler.onUploadComplete(assetId, file);\n          if (result.url) {\n            finalUrl = result.url;\n            // Clean up object URL since we have the real URL now\n            URL.revokeObjectURL(objectUrl);\n            setPreviewUrl(null);\n          }\n        }\n\n        setUploadState(\"idle\");\n        onChange?.(finalUrl);\n        onUploadComplete?.(finalUrl);\n      } catch (err) {\n        setUploadState(\"error\");\n        setError(err instanceof Error ? err.message : \"Upload failed\");\n        handler.onError?.(err instanceof Error ? err : new Error(\"Upload failed\"), file);\n      }\n    },\n    [accept, handler, maxSize, onChange, onUploadComplete, previewUrl],\n  );\n\n  const displayUrl = previewUrl || value;\n  const isLoading = uploadState === \"uploading\" || uploadState === \"processing\";\n\n  return (\n    <div className={cn(\"flex flex-col items-center gap-2\", className)} {...props}>\n      <div\n        role=\"button\"\n        tabIndex={disabled ? -1 : 0}\n        onClick={handleClick}\n        onKeyDown={(e) => {\n          if (e.key === \"Enter\" || e.key === \" \") {\n            handleClick();\n          }\n        }}\n        className={cn(\n          avatarVariants({ size }),\n          disabled && \"opacity-50 cursor-not-allowed\",\n          \"focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2\",\n        )}\n      >\n        <input\n          ref={inputRef}\n          type=\"file\"\n          accept={accept.join(\",\")}\n          onChange={handleFileSelect}\n          className=\"hidden\"\n          disabled={disabled || isLoading}\n        />\n\n        {/* Avatar image or fallback */}\n        {displayUrl ? (\n          <img src={displayUrl} alt=\"Avatar\" className=\"h-full w-full object-cover\" />\n        ) : fallback ? (\n          <span\n            className={cn(\n              \"font-medium text-muted-foreground uppercase\",\n              size === \"sm\" && \"text-lg\",\n              size === \"default\" && \"text-xl\",\n              size === \"lg\" && \"text-2xl\",\n              size === \"xl\" && \"text-3xl\",\n            )}\n          >\n            {fallback.slice(0, 2)}\n          </span>\n        ) : (\n          <User className={cn(iconVariants({ size }))} />\n        )}\n\n        {/* Hover overlay */}\n        {!disabled && !isLoading && (\n          <div className={cn(overlayVariants({ size }))}>\n            <Camera className=\"h-6 w-6 text-white\" />\n          </div>\n        )}\n\n        {/* Loading overlay */}\n        {isLoading && (\n          <div className=\"absolute inset-0 bg-black/60 flex items-center justify-center\">\n            <Loader2 className=\"h-6 w-6 text-white animate-spin\" />\n          </div>\n        )}\n\n        {/* Remove button */}\n        {allowRemove && displayUrl && !disabled && !isLoading && (\n          <button\n            type=\"button\"\n            onClick={handleRemove}\n            className=\"absolute -top-1 -right-1 h-6 w-6 rounded-full bg-destructive text-destructive-foreground flex items-center justify-center hover:bg-destructive/90 transition-colors\"\n          >\n            <X className=\"h-3 w-3\" />\n          </button>\n        )}\n      </div>\n\n      {/* Helper text */}\n      <div className=\"text-center\">\n        {error ? (\n          <p className=\"text-xs text-destructive\">{error}</p>\n        ) : isLoading ? (\n          <p className=\"text-xs text-muted-foreground\">\n            {uploadState === \"uploading\" ? \"Uploading...\" : \"Processing...\"}\n          </p>\n        ) : (\n          <p className=\"text-xs text-muted-foreground\">Click to {displayUrl ? \"change\" : \"upload\"}</p>\n        )}\n      </div>\n    </div>\n  );\n}\n\nAvatarUpload.displayName = \"AvatarUpload\";\n"]}