@@ -0,0 +1,14 @@
+
@@ -0,0 +1,3 @@
+
@@ -0,0 +1,3 @@
+
@@ -0,0 +1,6 @@
+
@@ -0,0 +1,138 @@
+.pointer {
+ cursor: pointer;
+}
+
+.container {
+ position: relative;
+ width: 46px;
+ margin: -12px 0;
+ height: 46px;
+ flex-shrink: 0;
+ background-color: #40404e;
+ border-radius: 4px;
+}
+
+.previewImage {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+ border-radius: 4px;
+}
+
+.previewIcon {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+ background-color: #8280FF;
+}
+
+.previewClickable {
+ cursor: pointer;
+}
+
+.tooltipIconPlaceholder {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 24px;
+ background-color: #2a2a2e;
+ border-radius: 12px;
+ padding-bottom: 24px;
+ min-width: 128px;
+ min-height: 144px;
+}
+
+.tooltipContent {
+ position: relative;
+ display: inline-block;
+ background-color: #222222;
+ border-radius: 12px;
+ display: flex;
+ min-height: 144px;
+ min-width: 128px;
+
+ &.tooltipContentSvg {
+ padding: 40px;
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 50%;
+ background: linear-gradient(to top, #151518, transparent);
+ pointer-events: none;
+ border-radius: 0 0 10px 10px;
+ z-index: 0;
+ }
+}
+
+.tooltipImage {
+ display: block;
+ min-height: 144px;
+ min-width: 128px;
+ max-width: 300px;
+ max-height: 300px;
+ object-fit: contain;
+ border-radius: 12px;
+}
+
+.tooltipText {
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: 8px 8px;
+ height: 100%;
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ gap: 2px;
+ font-size: 13px;
+ z-index: 1;
+
+ .tooltipTextItem {
+ display: flex;
+ justify-content: space-between;
+ }
+}
+
+.fileName {
+ min-width: 0;
+ overflow: hidden;
+}
+
+.dimensionsText {
+ background-color: #151518;
+ border-radius: 12px;
+ padding: 4px 8px;
+}
+
+.closeButton {
+ position: absolute;
+ top: -6px;
+ right: -4px;
+ width: 12px;
+ height: 12px;
+ padding: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ background-color: rgba(0, 0, 0, 0.8);
+ cursor: pointer;
+
+ &:hover {
+ background-color: rgba(0, 0, 0, 1);
+ }
+}
+
+.hiddenInput {
+ display: none;
+}
@@ -1,8 +1,9 @@
import React, { useRef, useState } from 'react'
-import { Box, Typography } from '@mui/material'
import Image from 'next/image'
+import { Box, Tooltip, Typography } from '@mui/material'
-import { TooltipCustom } from '#/shared'
+import { getFileTypeIcon, isImageFile } from '#/shared/lib/helpers'
+import styles from './load_image.module.scss'
interface IProps {
loading: boolean
@@ -10,6 +11,8 @@ interface IProps {
image: File | null | undefined
imageLoad?: React.ChangeEventHandler
types: string[]
+ fileNameMaxLength?: number
+ desktop?: boolean
}
const acceptTypes: any = {
@@ -23,50 +26,150 @@ const acceptTypes: any = {
text: '',
}
-export const LoadImage = ({ loading, unpinImage, image, imageLoad, types }: IProps) => {
+const formatFileSize = (bytes: number) => {
+ if (bytes < 1024) return `${bytes} B`
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`
+}
+
+
+const formatFileName = (name: string, maxLength: number = 30) => {
+ const lastDot = name.lastIndexOf('.')
+ const baseName = lastDot > 0 ? name.slice(0, lastDot) : name
+ const extWithMeta = lastDot > 0 ? name.slice(lastDot + 1) : ''
+ const ext = extWithMeta.split('?')[0]
+ if (baseName.length <= maxLength) return name
+ return `${baseName.slice(0, maxLength)}...${ext}`
+}
+
+export const LoadImage = ({ loading, unpinImage, image, imageLoad, types, fileNameMaxLength, desktop }: IProps) => {
const ref = useRef(null)
const [inputTypes, setInputTypes] = useState('')
+ const [previewUrl, setPreviewUrl] = useState(null)
+ const [dimensions, setDimensions] = useState<{ width: number; height: number } | null>(null)
React.useEffect(() => {
setInputTypes(types.map((el) => acceptTypes[el]).toString())
}, [types])
+ React.useEffect(() => {
+ if (!image) {
+ setPreviewUrl(null)
+ setDimensions(null)
+ return
+ }
+ if (!isImageFile(image)) {
+ setPreviewUrl(null)
+ setDimensions(null)
+ return
+ }
+ const url = URL.createObjectURL(image)
+ setPreviewUrl(url)
+
+ const img = new window.Image()
+ img.onload = () => {
+ setDimensions({ width: img.naturalWidth, height: img.naturalHeight })
+ }
+ img.src = url
+
+ return () => URL.revokeObjectURL(url)
+ }, [image])
+
if (!imageLoad || loading) {
return null
}
if (image) {
+ const isImage = isImageFile(image)
+ const fileIcon = getFileTypeIcon(image)
+ const isSvg = image.name.toLowerCase().split('?')[0].endsWith('.svg')
+
+ const tooltipContent = (
+
+ {isImage && previewUrl ? (
+
+ ) : (
+
+
+
+ )}
+
+
+ {isImage && dimensions && (
+
+ {dimensions.width}x{dimensions.height}px
+
+ )}
+
+ {formatFileSize(image.size)}
+
+
+
+
+ {formatFileName(image.name, isImage ? 30 : 15)}
+
+
+
+
+ )
+
return (
-
+
+
+ {isImage && previewUrl ? (
+ { e.stopPropagation(); unpinImage?.() } : undefined}
+ />
+ ) : (
+ { e.stopPropagation(); unpinImage?.() } : undefined}
+ >
+
+
+ )}
+
+ {
+ e.stopPropagation()
+ unpinImage?.()
+ }}
+ >
+
+
+
)
}
return (
<>
-
+