{"version":3,"file":"useImagePicker.hook.cjs","sources":["../../../../../src/components/forms/image-picker/hooks/useImagePicker.hook.ts"],"sourcesContent":["import {\r\n    useCallback,\r\n    useEffect,\r\n    useRef,\r\n    useState,\r\n    type ChangeEvent,\r\n    type DragEvent,\r\n} from 'react'\r\n\r\nimport {\r\n    IMAGE_PICKER_DEFAULT_ACCEPT,\r\n    IMAGE_PICKER_DEFAULT_LABELS,\r\n    IMAGE_PICKER_MOBILE_LABELS,\r\n} from '@components/forms/image-picker/constants/imagePickerDefaults.const.ts'\r\nimport type {\r\n    UseImagePickerOptions,\r\n    UseImagePickerReturn,\r\n} from '@components/forms/image-picker/hooks/types'\r\nimport type {\r\n    ImagePickerValidationReason,\r\n    ImagePickerValue,\r\n} from '@components/forms/image-picker/types/ImagePicker.types.ts'\r\nimport {\r\n    acceptsImagePickerFile,\r\n    hasImagePickerFiles,\r\n    isImagePickerFile,\r\n    syncImagePickerInput,\r\n} from '@components/forms/image-picker/utils/imagePicker.utils.ts'\r\n\r\n/**\r\n * Manages value state and browser interactions for ImagePicker.\r\n *\r\n * Supports controlled and uncontrolled values, local preview URLs, native\r\n * input synchronization, file validation, chooser opening, drag and drop, and\r\n * removal. When cropping is enabled, accepted files wait in a pending state\r\n * until the crop dialog confirms them. The returned handlers are ready to pass\r\n * to the ImagePicker subcomponents.\r\n */\r\nexport const useImagePicker = ({\r\n    value,\r\n    defaultValue = null,\r\n    onValueChange,\r\n    accept = IMAGE_PICKER_DEFAULT_ACCEPT,\r\n    maxSize,\r\n    onValidationError,\r\n    disabled = false,\r\n    disableChange = false,\r\n    disableRemove = false,\r\n    isMobile = false,\r\n    labels,\r\n    crop = false,\r\n}: UseImagePickerOptions): UseImagePickerReturn => {\r\n    const inputRef = useRef<HTMLInputElement>(null)\r\n    const [uncontrolledValue, setUncontrolledValue] =\r\n        useState<ImagePickerValue>(defaultValue)\r\n    const [filePreviewUrl, setFilePreviewUrl] = useState<string>()\r\n    const [validationReason, setValidationReason] =\r\n        useState<ImagePickerValidationReason>()\r\n    const [isDragging, setIsDragging] = useState(false)\r\n    const [pendingCropFile, setPendingCropFile] = useState<File>()\r\n\r\n    const isControlled = value !== undefined\r\n    const currentValue = isControlled ? value : uncontrolledValue\r\n    const hasValue = currentValue !== null\r\n    const isChangeDisabled = disabled || disableChange\r\n    const isRemoveDisabled = disabled || disableRemove\r\n    const resolvedLabels = {\r\n        ...(isMobile ? IMAGE_PICKER_MOBILE_LABELS : IMAGE_PICKER_DEFAULT_LABELS),\r\n        ...labels,\r\n    }\r\n    const previewUrl = typeof currentValue === 'string'\r\n        ? currentValue\r\n        : filePreviewUrl\r\n    const validationMessage = validationReason\r\n        ? resolvedLabels[validationReason]\r\n        : undefined\r\n\r\n    useEffect(() => {\r\n        if (\r\n            !isImagePickerFile(currentValue) ||\r\n            typeof URL === 'undefined' ||\r\n            typeof URL.createObjectURL !== 'function'\r\n        ) {\r\n            setFilePreviewUrl(undefined)\r\n            return\r\n        }\r\n\r\n        const objectUrl = URL.createObjectURL(currentValue)\r\n        setFilePreviewUrl(objectUrl)\r\n\r\n        return () => {\r\n            if (typeof URL.revokeObjectURL === 'function') {\r\n                URL.revokeObjectURL(objectUrl)\r\n            }\r\n        }\r\n    }, [currentValue])\r\n\r\n    useEffect(() => {\r\n        syncImagePickerInput(inputRef.current, currentValue)\r\n    }, [currentValue])\r\n\r\n    const updateValue = useCallback(\r\n        (nextValue: ImagePickerValue) => {\r\n            if (!isControlled) {\r\n                setUncontrolledValue(nextValue)\r\n            }\r\n            onValueChange?.(nextValue)\r\n        },\r\n        [isControlled, onValueChange],\r\n    )\r\n\r\n    const handleOpen = useCallback(() => {\r\n        if (!isChangeDisabled) {\r\n            inputRef.current?.click()\r\n        }\r\n    }, [isChangeDisabled])\r\n\r\n    const commitFile = useCallback(\r\n        (file: File) => {\r\n            setValidationReason(undefined)\r\n            syncImagePickerInput(inputRef.current, file)\r\n            updateValue(file)\r\n        },\r\n        [updateValue],\r\n    )\r\n\r\n    const handleFile = useCallback(\r\n        (file: File) => {\r\n            if (isChangeDisabled) {\r\n                return\r\n            }\r\n\r\n            let reason: ImagePickerValidationReason | undefined\r\n\r\n            if (!acceptsImagePickerFile(file, accept)) {\r\n                reason = 'invalidType'\r\n            } else if (maxSize !== undefined && file.size > maxSize) {\r\n                reason = 'maxSize'\r\n            }\r\n\r\n            if (reason) {\r\n                setValidationReason(reason)\r\n                syncImagePickerInput(inputRef.current, currentValue)\r\n                onValidationError?.(\r\n                    reason === 'maxSize'\r\n                        ? { reason, file, maxSize }\r\n                        : { reason, file },\r\n                )\r\n                return\r\n            }\r\n\r\n            setValidationReason(undefined)\r\n            if (crop) {\r\n                syncImagePickerInput(inputRef.current, currentValue)\r\n                setPendingCropFile(file)\r\n                return\r\n            }\r\n\r\n            commitFile(file)\r\n        },\r\n        [\r\n            accept,\r\n            commitFile,\r\n            crop,\r\n            currentValue,\r\n            isChangeDisabled,\r\n            maxSize,\r\n            onValidationError,\r\n        ],\r\n    )\r\n\r\n    const handleInputChange = useCallback(\r\n        (event: ChangeEvent<HTMLInputElement>) => {\r\n            const file = event.target.files?.[0]\r\n            if (file) {\r\n                handleFile(file)\r\n            }\r\n        },\r\n        [handleFile],\r\n    )\r\n\r\n    const handleDragOver = useCallback(\r\n        (event: DragEvent<HTMLButtonElement>) => {\r\n            if (!hasImagePickerFiles(event)) {\r\n                return\r\n            }\r\n\r\n            event.preventDefault()\r\n            event.dataTransfer.dropEffect = isChangeDisabled ? 'none' : 'copy'\r\n            if (!isChangeDisabled) {\r\n                setIsDragging(true)\r\n            }\r\n        },\r\n        [isChangeDisabled],\r\n    )\r\n\r\n    const handleDragLeave = useCallback(\r\n        (event: DragEvent<HTMLButtonElement>) => {\r\n            if (event.target !== event.currentTarget) {\r\n                return\r\n            }\r\n\r\n            const relatedTarget = event.relatedTarget\r\n            if (\r\n                typeof Node !== 'undefined'\r\n                && relatedTarget instanceof Node\r\n                && event.currentTarget.contains(relatedTarget)\r\n            ) {\r\n                return\r\n            }\r\n\r\n            setIsDragging(false)\r\n        },\r\n        [],\r\n    )\r\n\r\n    const handleDrop = useCallback(\r\n        (event: DragEvent<HTMLButtonElement>) => {\r\n            if (!hasImagePickerFiles(event)) {\r\n                return\r\n            }\r\n\r\n            event.preventDefault()\r\n            setIsDragging(false)\r\n            if (isChangeDisabled) {\r\n                return\r\n            }\r\n\r\n            const file = event.dataTransfer.files?.[0]\r\n            if (file) {\r\n                handleFile(file)\r\n            }\r\n        },\r\n        [handleFile, isChangeDisabled],\r\n    )\r\n\r\n    const handleClear = useCallback(() => {\r\n        if (isRemoveDisabled) {\r\n            return\r\n        }\r\n\r\n        setPendingCropFile(undefined)\r\n        setValidationReason(undefined)\r\n        setIsDragging(false)\r\n        updateValue(null)\r\n        if (inputRef.current) {\r\n            inputRef.current.value = ''\r\n        }\r\n    }, [isRemoveDisabled, updateValue])\r\n\r\n    const handleCropCancel = useCallback(() => {\r\n        setPendingCropFile(undefined)\r\n        syncImagePickerInput(inputRef.current, currentValue)\r\n    }, [currentValue])\r\n\r\n    const handleCropConfirm = useCallback(\r\n        (file: File) => {\r\n            setPendingCropFile(undefined)\r\n            commitFile(file)\r\n        },\r\n        [commitFile],\r\n    )\r\n\r\n    return {\r\n        inputRef,\r\n        previewUrl,\r\n        resolvedLabels,\r\n        validationMessage,\r\n        hasValue,\r\n        isChangeDisabled,\r\n        isRemoveDisabled,\r\n        isDragging,\r\n        pendingCropFile,\r\n        handleOpen,\r\n        handleInputChange,\r\n        handleDragOver,\r\n        handleDragLeave,\r\n        handleDrop,\r\n        handleClear,\r\n        handleCropCancel,\r\n        handleCropConfirm,\r\n    }\r\n}\r\n"],"names":["useImagePicker","value","defaultValue","onValueChange","accept","IMAGE_PICKER_DEFAULT_ACCEPT","maxSize","onValidationError","disabled","disableChange","disableRemove","isMobile","labels","crop","inputRef","useRef","uncontrolledValue","setUncontrolledValue","useState","filePreviewUrl","setFilePreviewUrl","validationReason","setValidationReason","isDragging","setIsDragging","pendingCropFile","setPendingCropFile","isControlled","currentValue","hasValue","isChangeDisabled","isRemoveDisabled","resolvedLabels","IMAGE_PICKER_MOBILE_LABELS","IMAGE_PICKER_DEFAULT_LABELS","previewUrl","validationMessage","useEffect","isImagePickerFile","objectUrl","syncImagePickerInput","updateValue","useCallback","nextValue","handleOpen","commitFile","file","handleFile","reason","acceptsImagePickerFile","handleInputChange","event","handleDragOver","hasImagePickerFiles","handleDragLeave","relatedTarget","handleDrop","handleClear","handleCropCancel","handleCropConfirm"],"mappings":"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"}