@@ -23,7 +23,7 @@ import { imageToCompareChanged, selectGallerySlice, selectionChanged } from 'fea
2323import { navigationApi } from 'features/ui/layouts/navigation-api' ;
2424import { VIEWER_PANEL_ID } from 'features/ui/layouts/shared' ;
2525import type { MouseEvent , MouseEventHandler } from 'react' ;
26- import { memo , useCallback , useEffect , useMemo , useState } from 'react' ;
26+ import { memo , useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
2727import { PiImageBold } from 'react-icons/pi' ;
2828import { imagesApi } from 'services/api/endpoints/images' ;
2929import type { ImageDTO } from 'services/api/types' ;
@@ -42,45 +42,42 @@ const galleryImageContainerSX = {
4242 '&[data-is-dragging=true]' : {
4343 opacity : 0.3 ,
4444 } ,
45- [ `.${ GALLERY_IMAGE_CLASS } ` ] : {
46- touchAction : 'none' ,
47- userSelect : 'none' ,
48- webkitUserSelect : 'none' ,
49- position : 'relative' ,
50- justifyContent : 'center' ,
51- alignItems : 'center' ,
52- aspectRatio : '1/1' ,
53- '::before' : {
54- content : '""' ,
55- display : 'inline-block' ,
56- position : 'absolute' ,
57- top : 0 ,
58- left : 0 ,
59- right : 0 ,
60- bottom : 0 ,
61- pointerEvents : 'none' ,
62- borderRadius : 'base' ,
63- } ,
64- '&[data-selected=true]::before' : {
65- boxShadow :
66- 'inset 0px 0px 0px 3px var(--invoke-colors-invokeBlue-500), inset 0px 0px 0px 4px var(--invoke-colors-invokeBlue-800)' ,
67- } ,
68- '&[data-selected-for-compare=true]::before' : {
69- boxShadow :
70- 'inset 0px 0px 0px 3px var(--invoke-colors-invokeGreen-300), inset 0px 0px 0px 4px var(--invoke-colors-invokeGreen-800)' ,
71- } ,
72- '&:hover::before' : {
73- boxShadow :
74- 'inset 0px 0px 0px 1px var(--invoke-colors-invokeBlue-300), inset 0px 0px 0px 2px var(--invoke-colors-invokeBlue-800)' ,
75- } ,
76- '&:hover[data-selected=true]::before' : {
77- boxShadow :
78- 'inset 0px 0px 0px 3px var(--invoke-colors-invokeBlue-400), inset 0px 0px 0px 4px var(--invoke-colors-invokeBlue-800)' ,
79- } ,
80- '&:hover[data-selected-for-compare=true]::before' : {
81- boxShadow :
82- 'inset 0px 0px 0px 3px var(--invoke-colors-invokeGreen-200), inset 0px 0px 0px 4px var(--invoke-colors-invokeGreen-800)' ,
83- } ,
45+ userSelect : 'none' ,
46+ webkitUserSelect : 'none' ,
47+ position : 'relative' ,
48+ justifyContent : 'center' ,
49+ alignItems : 'center' ,
50+ aspectRatio : '1/1' ,
51+ '::before' : {
52+ content : '""' ,
53+ display : 'inline-block' ,
54+ position : 'absolute' ,
55+ top : 0 ,
56+ left : 0 ,
57+ right : 0 ,
58+ bottom : 0 ,
59+ pointerEvents : 'none' ,
60+ borderRadius : 'base' ,
61+ } ,
62+ '&[data-selected=true]::before' : {
63+ boxShadow :
64+ 'inset 0px 0px 0px 3px var(--invoke-colors-invokeBlue-500), inset 0px 0px 0px 4px var(--invoke-colors-invokeBlue-800)' ,
65+ } ,
66+ '&[data-selected-for-compare=true]::before' : {
67+ boxShadow :
68+ 'inset 0px 0px 0px 3px var(--invoke-colors-invokeGreen-300), inset 0px 0px 0px 4px var(--invoke-colors-invokeGreen-800)' ,
69+ } ,
70+ '&:hover::before' : {
71+ boxShadow :
72+ 'inset 0px 0px 0px 1px var(--invoke-colors-invokeBlue-300), inset 0px 0px 0px 2px var(--invoke-colors-invokeBlue-800)' ,
73+ } ,
74+ '&:hover[data-selected=true]::before' : {
75+ boxShadow :
76+ 'inset 0px 0px 0px 3px var(--invoke-colors-invokeBlue-400), inset 0px 0px 0px 4px var(--invoke-colors-invokeBlue-800)' ,
77+ } ,
78+ '&:hover[data-selected-for-compare=true]::before' : {
79+ boxShadow :
80+ 'inset 0px 0px 0px 3px var(--invoke-colors-invokeGreen-200), inset 0px 0px 0px 4px var(--invoke-colors-invokeGreen-800)' ,
8481 } ,
8582} satisfies SystemStyleObject ;
8683
@@ -142,8 +139,7 @@ export const GalleryImage = memo(({ imageDTO }: Props) => {
142139 const [ dragPreviewState , setDragPreviewState ] = useState <
143140 DndDragPreviewSingleImageState | DndDragPreviewMultipleImageState | null
144141 > ( null ) ;
145- // Must use callback ref - else chakra's Image fallback prop will break the ref & dnd
146- const [ element , ref ] = useState < HTMLDivElement | null > ( null ) ;
142+ const ref = useRef < HTMLDivElement > ( null ) ;
147143 const selectIsSelectedForCompare = useMemo (
148144 ( ) => createSelector ( selectGallerySlice , ( gallery ) => gallery . imageToCompare === imageDTO . image_name ) ,
149145 [ imageDTO . image_name ]
@@ -156,6 +152,7 @@ export const GalleryImage = memo(({ imageDTO }: Props) => {
156152 const isSelected = useAppSelector ( selectIsSelected ) ;
157153
158154 useEffect ( ( ) => {
155+ const element = ref . current ;
159156 if ( ! element ) {
160157 return ;
161158 }
@@ -221,7 +218,7 @@ export const GalleryImage = memo(({ imageDTO }: Props) => {
221218 } ,
222219 } )
223220 ) ;
224- } , [ element , imageDTO , store ] ) ;
221+ } , [ imageDTO , store ] ) ;
225222
226223 const [ isHovered , setIsHovered ] = useState ( false ) ;
227224
@@ -240,34 +237,35 @@ export const GalleryImage = memo(({ imageDTO }: Props) => {
240237 navigationApi . focusPanelInActiveTab ( VIEWER_PANEL_ID ) ;
241238 } , [ store ] ) ;
242239
243- useImageContextMenu ( imageDTO , element ) ;
240+ useImageContextMenu ( imageDTO , ref ) ;
244241
245242 return (
246243 < >
247- < Box sx = { galleryImageContainerSX } data-is-dragging = { isDragging } data-image-name = { imageDTO . image_name } >
248- < Flex
249- ref = { ref }
250- role = "button"
251- className = { GALLERY_IMAGE_CLASS }
252- onMouseOver = { onMouseOver }
253- onMouseOut = { onMouseOut }
254- onClick = { onClick }
255- onDoubleClick = { onDoubleClick }
256- data-selected = { isSelected }
257- data-selected-for-compare = { isSelectedForCompare }
258- >
259- < Image
260- src = { imageDTO . thumbnail_url }
261- w = { imageDTO . width }
262- fallback = { < GalleryImagePlaceholder /> }
263- objectFit = "contain"
264- maxW = "full"
265- maxH = "full"
266- borderRadius = "base"
267- />
268- < GalleryImageHoverIcons imageDTO = { imageDTO } isHovered = { isHovered } />
269- </ Flex >
270- </ Box >
244+ < Flex
245+ ref = { ref }
246+ sx = { galleryImageContainerSX }
247+ data-is-dragging = { isDragging }
248+ data-image-name = { imageDTO . image_name }
249+ role = "button"
250+ onMouseOver = { onMouseOver }
251+ onMouseOut = { onMouseOut }
252+ onClick = { onClick }
253+ onDoubleClick = { onDoubleClick }
254+ data-selected = { isSelected }
255+ data-selected-for-compare = { isSelectedForCompare }
256+ >
257+ < Image
258+ pointerEvents = { 'none' }
259+ src = { imageDTO . thumbnail_url }
260+ w = { imageDTO . width }
261+ fallback = { < GalleryImagePlaceholder /> }
262+ objectFit = "contain"
263+ maxW = "full"
264+ maxH = "full"
265+ borderRadius = "base"
266+ />
267+ < GalleryImageHoverIcons imageDTO = { imageDTO } isHovered = { isHovered } />
268+ </ Flex >
271269 { dragPreviewState ?. type === 'multiple-image' ? createMultipleImageDragPreview ( dragPreviewState ) : null }
272270 { dragPreviewState ?. type === 'single-image' ? createSingleImageDragPreview ( dragPreviewState ) : null }
273271 </ >
0 commit comments