@mgonza02/goal-image-gallery 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to the GoalImageGallery project will be documented in this f
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.1] - 2025-07-14
|
|
9
|
+
### 🐛 Bug Fixes
|
|
10
|
+
- **Fixed Image Gallery Modal**: Resolved issues with the image gallery modal not displaying correctly
|
|
11
|
+
- **Improved Image Handling**: Enhanced image error handling and loading states
|
|
12
|
+
- **Modal Responsiveness**: Ensured the modal is fully responsive and adapts to different screen sizes
|
|
13
|
+
- **Accessibility Improvements**: Enhanced keyboard navigation and ARIA attributes for better accessibility
|
|
14
|
+
- **Code Cleanup**: Removed unused imports and optimized component structure
|
|
15
|
+
- **Remove styled-components**: Replaced styled-components with MUI's Box component for better consistency
|
|
16
|
+
|
|
8
17
|
## [1.1.0] - 2025-07-14
|
|
9
18
|
|
|
10
19
|
### 🐛 Bug Fixes
|
package/lib/GoalImageGallery.js
CHANGED
|
@@ -236,7 +236,6 @@ const GoalImageGallery = _ref => {
|
|
|
236
236
|
slotProps = {}
|
|
237
237
|
} = _ref;
|
|
238
238
|
const theme = useTheme();
|
|
239
|
-
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
|
240
239
|
const [updatable, setUpdatable] = useState(false);
|
|
241
240
|
const {
|
|
242
241
|
selector: ImageSelector
|
|
@@ -257,7 +256,6 @@ const GoalImageGallery = _ref => {
|
|
|
257
256
|
selectedImageIndex,
|
|
258
257
|
selectingImage,
|
|
259
258
|
imageList,
|
|
260
|
-
selectedImage,
|
|
261
259
|
zoomLevel,
|
|
262
260
|
loading,
|
|
263
261
|
removable,
|
|
@@ -282,8 +280,6 @@ const GoalImageGallery = _ref => {
|
|
|
282
280
|
|
|
283
281
|
// Zoom and navigation handlers
|
|
284
282
|
const {
|
|
285
|
-
handleZoomIn,
|
|
286
|
-
handleZoomOut,
|
|
287
283
|
handlePreviousImage,
|
|
288
284
|
handleNextImage
|
|
289
285
|
} = useImageZoom(getImageUrl, imageList);
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { Grid, Card, CardContent
|
|
2
|
+
import { Grid, Card, CardContent } from '@mui/material';
|
|
4
3
|
import { useTheme } from '@mui/material/styles';
|
|
5
4
|
import ImageGalleryItem from './ImageGalleryItem';
|
|
6
5
|
import ImageGalleryEmptyState from './ImageGalleryEmptyState';
|
|
7
6
|
import { StyledImageGridContainer } from '../styles/styled-components';
|
|
8
|
-
import { getGridColumns } from '../utils/image-utils';
|
|
9
7
|
|
|
10
8
|
/**
|
|
11
9
|
* Image grid component for displaying gallery images
|
|
@@ -30,8 +28,6 @@ const ImageGalleryGrid = _ref => {
|
|
|
30
28
|
onDownloadImage
|
|
31
29
|
} = _ref;
|
|
32
30
|
const theme = useTheme();
|
|
33
|
-
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
|
34
|
-
const isTablet = useMediaQuery(theme.breakpoints.down('lg'));
|
|
35
31
|
if (imageList.length === 0) {
|
|
36
32
|
return /*#__PURE__*/_jsx(Card, {
|
|
37
33
|
elevation: 2,
|
|
@@ -53,8 +49,11 @@ const ImageGalleryGrid = _ref => {
|
|
|
53
49
|
container: true,
|
|
54
50
|
spacing: 2,
|
|
55
51
|
children: imageList.map((image, index) => /*#__PURE__*/_jsx(Grid, {
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
size: {
|
|
53
|
+
xs: 6,
|
|
54
|
+
sm: multiple ? 4 : 6,
|
|
55
|
+
md: multiple ? 3 : 4
|
|
56
|
+
},
|
|
58
57
|
sx: {
|
|
59
58
|
position: 'relative'
|
|
60
59
|
},
|
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import { Box, IconButton, Skeleton, Tooltip, Typography, Button } from '@mui/material';
|
|
4
4
|
import { alpha, useTheme } from '@mui/material/styles';
|
|
5
5
|
import { ChangeCircle as ChangeIcon, Download as DownloadIcon, Visibility as ViewIcon, Add as AddIcon, Delete as DeleteIcon } from '@mui/icons-material';
|
|
6
|
-
import {
|
|
6
|
+
import { getImageContainerStyles, getImageOverlayStyles } from '../styles/styled-components';
|
|
7
7
|
import { handleImageError } from '../utils/image-utils';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -30,8 +30,9 @@ const ImageGalleryItem = _ref => {
|
|
|
30
30
|
|
|
31
31
|
// Handle add button (+) image
|
|
32
32
|
if (image.image_code === '+') {
|
|
33
|
-
return /*#__PURE__*/_jsx(
|
|
33
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
34
34
|
sx: {
|
|
35
|
+
...getImageContainerStyles(theme),
|
|
35
36
|
height: 200,
|
|
36
37
|
display: 'flex',
|
|
37
38
|
alignItems: 'center',
|
|
@@ -62,7 +63,8 @@ const ImageGalleryItem = _ref => {
|
|
|
62
63
|
})
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
|
-
return /*#__PURE__*/_jsxs(
|
|
66
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
67
|
+
sx: getImageContainerStyles(theme),
|
|
66
68
|
children: [loading && /*#__PURE__*/_jsx(Skeleton, {
|
|
67
69
|
variant: "rectangular",
|
|
68
70
|
width: "100%",
|
|
@@ -84,8 +86,9 @@ const ImageGalleryItem = _ref => {
|
|
|
84
86
|
objectFit: 'cover',
|
|
85
87
|
display: loading ? 'none' : 'block'
|
|
86
88
|
}
|
|
87
|
-
}, image.image_code), /*#__PURE__*/_jsxs(
|
|
89
|
+
}, image.image_code), /*#__PURE__*/_jsxs(Box, {
|
|
88
90
|
className: "image-overlay",
|
|
91
|
+
sx: getImageOverlayStyles(theme),
|
|
89
92
|
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
90
93
|
title: "Ver imagen",
|
|
91
94
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import PropTypes from 'prop-types';
|
|
3
2
|
import { Modal, Zoom, Backdrop, Typography, IconButton, Stack, Chip, Tooltip, Box, useMediaQuery, useTheme } from '@mui/material';
|
|
4
3
|
import { Close as CloseIcon, ZoomIn as ZoomInIcon, ZoomOut as ZoomOutIcon, ChevronLeft as ChevronLeftIcon, ChevronRight as ChevronRightIcon } from '@mui/icons-material';
|
|
5
|
-
import {
|
|
4
|
+
import { getModalContainerStyles, getModalHeaderStyles, getModalBodyStyles, getModalFooterStyles } from '../styles/styled-components';
|
|
6
5
|
import { handleImageError } from '../utils/image-utils';
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -42,9 +41,10 @@ const ImageGalleryModal = _ref => {
|
|
|
42
41
|
},
|
|
43
42
|
children: /*#__PURE__*/_jsx(Zoom, {
|
|
44
43
|
in: open,
|
|
45
|
-
children: /*#__PURE__*/_jsxs(
|
|
46
|
-
|
|
47
|
-
children: [/*#__PURE__*/_jsxs(
|
|
44
|
+
children: /*#__PURE__*/_jsxs(Box, {
|
|
45
|
+
sx: getModalContainerStyles(theme, isMobile),
|
|
46
|
+
children: [/*#__PURE__*/_jsxs(Box, {
|
|
47
|
+
sx: getModalHeaderStyles(theme),
|
|
48
48
|
children: [/*#__PURE__*/_jsxs(Typography, {
|
|
49
49
|
variant: "h6",
|
|
50
50
|
children: ["Imagen ", selectedImageIndex + 1, " de ", imageList.length]
|
|
@@ -77,7 +77,8 @@ const ImageGalleryModal = _ref => {
|
|
|
77
77
|
})
|
|
78
78
|
})]
|
|
79
79
|
})]
|
|
80
|
-
}), /*#__PURE__*/_jsx(
|
|
80
|
+
}), /*#__PURE__*/_jsx(Box, {
|
|
81
|
+
sx: getModalBodyStyles(theme),
|
|
81
82
|
children: /*#__PURE__*/_jsx(Box, {
|
|
82
83
|
sx: {
|
|
83
84
|
width: '100%',
|
|
@@ -105,7 +106,8 @@ const ImageGalleryModal = _ref => {
|
|
|
105
106
|
onError: e => handleImageError(e, noImageUrl)
|
|
106
107
|
})
|
|
107
108
|
})
|
|
108
|
-
}), imageList.length > 1 && /*#__PURE__*/_jsxs(
|
|
109
|
+
}), imageList.length > 1 && /*#__PURE__*/_jsxs(Box, {
|
|
110
|
+
sx: getModalFooterStyles(theme),
|
|
109
111
|
children: [/*#__PURE__*/_jsx(Tooltip, {
|
|
110
112
|
title: "Imagen anterior",
|
|
111
113
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
@@ -1,173 +1,142 @@
|
|
|
1
1
|
import { Box } from '@mui/material';
|
|
2
|
-
import { alpha
|
|
2
|
+
import { alpha } from '@mui/material/styles';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Styles for image containers with enhanced hover effects
|
|
6
6
|
*/
|
|
7
|
-
export const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
'
|
|
22
|
-
|
|
23
|
-
boxShadow: theme.shadows[4],
|
|
24
|
-
transform: 'translateY(-2px)',
|
|
25
|
-
'& .image-overlay': {
|
|
26
|
-
opacity: 1
|
|
27
|
-
}
|
|
7
|
+
export const getImageContainerStyles = theme => ({
|
|
8
|
+
position: 'relative',
|
|
9
|
+
borderRadius: theme.spacing(1.5),
|
|
10
|
+
overflow: 'hidden',
|
|
11
|
+
backgroundColor: theme.palette.background.paper,
|
|
12
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
13
|
+
cursor: 'pointer',
|
|
14
|
+
transition: theme.transitions.create(['border-color', 'box-shadow', 'transform'], {
|
|
15
|
+
duration: theme.transitions.duration.short
|
|
16
|
+
}),
|
|
17
|
+
'&:hover': {
|
|
18
|
+
borderColor: theme.palette.primary.main,
|
|
19
|
+
boxShadow: theme.shadows[4],
|
|
20
|
+
transform: 'translateY(-2px)',
|
|
21
|
+
'& .image-overlay': {
|
|
22
|
+
opacity: 1
|
|
28
23
|
}
|
|
29
|
-
}
|
|
24
|
+
}
|
|
30
25
|
});
|
|
31
26
|
|
|
32
27
|
/**
|
|
33
|
-
*
|
|
28
|
+
* Styles for image overlay with action buttons
|
|
34
29
|
*/
|
|
35
|
-
export const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
'
|
|
54
|
-
|
|
55
|
-
backgroundColor: alpha(theme.palette.common.black, 0.7),
|
|
56
|
-
margin: theme.spacing(0.5),
|
|
57
|
-
'&:hover': {
|
|
58
|
-
backgroundColor: alpha(theme.palette.common.black, 0.9)
|
|
59
|
-
}
|
|
30
|
+
export const getImageOverlayStyles = theme => ({
|
|
31
|
+
position: 'absolute',
|
|
32
|
+
top: 0,
|
|
33
|
+
left: 0,
|
|
34
|
+
right: 0,
|
|
35
|
+
bottom: 0,
|
|
36
|
+
background: alpha(theme.palette.common.black, 0.5),
|
|
37
|
+
display: 'flex',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
justifyContent: 'center',
|
|
40
|
+
opacity: 0,
|
|
41
|
+
transition: theme.transitions.create('opacity', {
|
|
42
|
+
duration: theme.transitions.duration.short
|
|
43
|
+
}),
|
|
44
|
+
'& .MuiIconButton-root': {
|
|
45
|
+
color: theme.palette.common.white,
|
|
46
|
+
backgroundColor: alpha(theme.palette.common.black, 0.7),
|
|
47
|
+
margin: theme.spacing(0.5),
|
|
48
|
+
'&:hover': {
|
|
49
|
+
backgroundColor: alpha(theme.palette.common.black, 0.9)
|
|
60
50
|
}
|
|
61
|
-
}
|
|
51
|
+
}
|
|
62
52
|
});
|
|
63
53
|
|
|
64
54
|
/**
|
|
65
|
-
*
|
|
55
|
+
* Styles for modal container
|
|
66
56
|
*/
|
|
67
|
-
export const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
borderRadius: theme.spacing(2),
|
|
82
|
-
overflow: 'hidden',
|
|
83
|
-
display: 'flex',
|
|
84
|
-
flexDirection: 'column',
|
|
85
|
-
boxShadow: 24
|
|
86
|
-
};
|
|
57
|
+
export const getModalContainerStyles = (theme, isMobile) => ({
|
|
58
|
+
top: '50%',
|
|
59
|
+
left: '50%',
|
|
60
|
+
transform: 'translate(-50%, -50%) !important',
|
|
61
|
+
position: 'absolute',
|
|
62
|
+
width: isMobile ? '95vw' : '90vw',
|
|
63
|
+
maxWidth: 1200,
|
|
64
|
+
height: isMobile ? '95vh' : '90vh',
|
|
65
|
+
backgroundColor: theme.palette.background.paper,
|
|
66
|
+
borderRadius: theme.spacing(2),
|
|
67
|
+
overflow: 'hidden',
|
|
68
|
+
display: 'flex',
|
|
69
|
+
flexDirection: 'column',
|
|
70
|
+
boxShadow: 24
|
|
87
71
|
});
|
|
88
72
|
|
|
89
73
|
/**
|
|
90
|
-
*
|
|
74
|
+
* Styles for modal header
|
|
91
75
|
*/
|
|
92
|
-
export const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
alignItems: 'center',
|
|
100
|
-
padding: theme.spacing(2),
|
|
101
|
-
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
102
|
-
backgroundColor: alpha(theme.palette.background.paper, 0.95)
|
|
103
|
-
};
|
|
76
|
+
export const getModalHeaderStyles = theme => ({
|
|
77
|
+
display: 'flex',
|
|
78
|
+
justifyContent: 'space-between',
|
|
79
|
+
alignItems: 'center',
|
|
80
|
+
padding: theme.spacing(2),
|
|
81
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
82
|
+
backgroundColor: alpha(theme.palette.background.paper, 0.95)
|
|
104
83
|
});
|
|
105
84
|
|
|
106
85
|
/**
|
|
107
|
-
*
|
|
86
|
+
* Styles for modal body
|
|
108
87
|
*/
|
|
109
|
-
export const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
justifyContent: 'center',
|
|
118
|
-
overflow: 'hidden',
|
|
119
|
-
position: 'relative',
|
|
120
|
-
backgroundColor: theme.palette.grey[50]
|
|
121
|
-
};
|
|
88
|
+
export const getModalBodyStyles = theme => ({
|
|
89
|
+
flex: 1,
|
|
90
|
+
display: 'flex',
|
|
91
|
+
alignItems: 'center',
|
|
92
|
+
justifyContent: 'center',
|
|
93
|
+
overflow: 'hidden',
|
|
94
|
+
position: 'relative',
|
|
95
|
+
backgroundColor: theme.palette.grey[50]
|
|
122
96
|
});
|
|
123
97
|
|
|
124
98
|
/**
|
|
125
|
-
*
|
|
99
|
+
* Styles for modal footer
|
|
126
100
|
*/
|
|
127
|
-
export const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
alignItems: 'center',
|
|
135
|
-
padding: theme.spacing(2),
|
|
136
|
-
borderTop: `1px solid ${theme.palette.divider}`,
|
|
137
|
-
backgroundColor: alpha(theme.palette.background.paper, 0.95)
|
|
138
|
-
};
|
|
101
|
+
export const getModalFooterStyles = theme => ({
|
|
102
|
+
display: 'flex',
|
|
103
|
+
justifyContent: 'space-between',
|
|
104
|
+
alignItems: 'center',
|
|
105
|
+
padding: theme.spacing(2),
|
|
106
|
+
borderTop: `1px solid ${theme.palette.divider}`,
|
|
107
|
+
backgroundColor: alpha(theme.palette.background.paper, 0.95)
|
|
139
108
|
});
|
|
140
109
|
|
|
141
110
|
/**
|
|
142
|
-
*
|
|
111
|
+
* Styles for empty state container
|
|
143
112
|
*/
|
|
144
|
-
export const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
justifyContent: 'center',
|
|
152
|
-
alignItems: 'center',
|
|
153
|
-
padding: theme.spacing(2),
|
|
154
|
-
minHeight: 300
|
|
155
|
-
};
|
|
113
|
+
export const getEmptyStateContainerStyles = theme => ({
|
|
114
|
+
display: 'flex',
|
|
115
|
+
flexDirection: 'column',
|
|
116
|
+
justifyContent: 'center',
|
|
117
|
+
alignItems: 'center',
|
|
118
|
+
padding: theme.spacing(2),
|
|
119
|
+
minHeight: 300
|
|
156
120
|
});
|
|
157
121
|
|
|
158
122
|
/**
|
|
159
|
-
*
|
|
123
|
+
* Styles for image grid container
|
|
160
124
|
*/
|
|
161
|
-
export const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
125
|
+
export const getImageGridContainerStyles = theme => ({
|
|
126
|
+
display: 'flex',
|
|
127
|
+
flexDirection: 'column',
|
|
128
|
+
justifyContent: 'center',
|
|
129
|
+
alignItems: 'center',
|
|
130
|
+
padding: theme.spacing(2),
|
|
131
|
+
minHeight: 200
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Legacy styled components exports for backward compatibility
|
|
135
|
+
export const StyledImageContainer = Box;
|
|
136
|
+
export const ImageOverlay = Box;
|
|
137
|
+
export const StyledModalContainer = Box;
|
|
138
|
+
export const StyledModalHeader = Box;
|
|
139
|
+
export const StyledModalBody = Box;
|
|
140
|
+
export const StyledModalFooter = Box;
|
|
141
|
+
export const StyledEmptyStateContainer = Box;
|
|
142
|
+
export const StyledImageGridContainer = Box;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mgonza02/goal-image-gallery",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Advanced, accessible, and highly customizable React image gallery component with multi-method upload, responsive design, and extensive TypeScript support",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "lib/index.js",
|