@mgonza02/goal-image-gallery 1.0.0

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.
@@ -0,0 +1,235 @@
1
+ # GoalImageGallery - Quick Reference
2
+
3
+ ## Basic Usage
4
+
5
+ ```javascript
6
+ import GoalImageGallery from './components/common/goal-image-gallery';
7
+
8
+ // Read-only gallery
9
+ <GoalImageGallery imageCodes={['img1', 'img2']} canEdit={false} />
10
+
11
+ // Editable gallery
12
+ <GoalImageGallery
13
+ imageCodes={images}
14
+ canEdit={true}
15
+ ownerEntity={{ id: 'entity-123' }}
16
+ imageHandlerApi={handleUpload}
17
+ afterUpload={refreshData}
18
+ multiple={true}
19
+ />
20
+ ```
21
+
22
+ ## Props Reference
23
+
24
+ | Prop | Type | Default | Description |
25
+ |------|------|---------|-------------|
26
+ | `imageCodes` | `string \| array` | - | Image codes to display |
27
+ | `canEdit` | `boolean` | `false` | Enable editing |
28
+ | `ownerEntity` | `object` | - | Owner entity data |
29
+ | `imageHandlerApi` | `function` | - | Upload handler function |
30
+ | `afterUpload` | `function` | - | Success callback |
31
+ | `multiple` | `boolean` | `false` | Allow multiple images |
32
+ | `permission` | `string` | - | Required permission |
33
+ | `emptyMessage` | `string` | `'No hay imΓ‘genes para mostrar'` | Empty state message |
34
+ | `showImageInfo` | `boolean` | `false` | Show image info |
35
+ | `allowDownload` | `boolean` | `true` | Enable downloads |
36
+
37
+ ## Upload Methods
38
+
39
+ ### 1. File Upload
40
+ ```javascript
41
+ // Users can:
42
+ // - Click "Add Image" button
43
+ // - Drag & drop files
44
+ // - Use file dialog
45
+ ```
46
+
47
+ ### 2. Clipboard Paste
48
+ ```javascript
49
+ // Users can:
50
+ // - Copy image (Ctrl+C)
51
+ // - Paste in gallery (Ctrl+V)
52
+ // - Automatically processed
53
+ ```
54
+
55
+ ### 3. URL Loading
56
+ ```javascript
57
+ // Users can:
58
+ // - Enter image URL
59
+ // - Load remote images
60
+ // - Validate URL format
61
+ ```
62
+
63
+ ## API Handler Example
64
+
65
+ ```javascript
66
+ const handleImageUpload = async (imageData) => {
67
+ try {
68
+ const response = await api.uploadImage({
69
+ ...imageData,
70
+ companyId: currentCompany,
71
+ entityId: ownerEntity.id
72
+ });
73
+
74
+ return {
75
+ success: true,
76
+ data: response.data,
77
+ message: 'Upload successful'
78
+ };
79
+ } catch (error) {
80
+ return {
81
+ success: false,
82
+ message: error.message
83
+ };
84
+ }
85
+ };
86
+ ```
87
+
88
+ ## Keyboard Shortcuts
89
+
90
+ | Key | Action |
91
+ |-----|--------|
92
+ | `←` / `β†’` | Navigate images |
93
+ | `+` / `=` | Zoom in |
94
+ | `-` | Zoom out |
95
+ | `Escape` | Close viewer |
96
+ | `Ctrl+V` | Paste image |
97
+
98
+ ## Common Patterns
99
+
100
+ ### Product Gallery
101
+ ```javascript
102
+ <GoalImageGallery
103
+ imageCodes={product.images}
104
+ canEdit={hasPermission('EDIT_PRODUCTS')}
105
+ ownerEntity={{ id: product.id, type: 'product' }}
106
+ imageHandlerApi={productApi.uploadImages}
107
+ afterUpload={refreshProduct}
108
+ multiple={true}
109
+ showImageInfo={true}
110
+ />
111
+ ```
112
+
113
+ ### User Avatar
114
+ ```javascript
115
+ <GoalImageGallery
116
+ imageCodes={[user.avatar]}
117
+ canEdit={isOwner}
118
+ ownerEntity={{ id: user.id, type: 'user' }}
119
+ imageHandlerApi={userApi.uploadAvatar}
120
+ afterUpload={refreshUser}
121
+ multiple={false}
122
+ emptyMessage="No avatar set"
123
+ />
124
+ ```
125
+
126
+ ### Document Attachments
127
+ ```javascript
128
+ <GoalImageGallery
129
+ imageCodes={document.attachments}
130
+ canEdit={canEditDocs}
131
+ ownerEntity={{ id: document.id, type: 'document' }}
132
+ imageHandlerApi={docApi.uploadAttachments}
133
+ afterUpload={refreshDocument}
134
+ multiple={true}
135
+ permission="EDIT_DOCUMENTS"
136
+ allowDownload={true}
137
+ />
138
+ ```
139
+
140
+ ## Error Handling
141
+
142
+ ```javascript
143
+ const handleUpload = async (imageData) => {
144
+ try {
145
+ // Validate file
146
+ if (imageData.size > 5 * 1024 * 1024) {
147
+ throw new Error('File too large');
148
+ }
149
+
150
+ // Upload
151
+ const response = await api.upload(imageData);
152
+
153
+ return {
154
+ success: true,
155
+ data: response.data
156
+ };
157
+ } catch (error) {
158
+ return {
159
+ success: false,
160
+ message: error.message
161
+ };
162
+ }
163
+ };
164
+ ```
165
+
166
+ ## Customization
167
+
168
+ ### Custom Empty Message
169
+ ```javascript
170
+ <GoalImageGallery
171
+ imageCodes={[]}
172
+ emptyMessage="Start your gallery by adding images"
173
+ canEdit={true}
174
+ // ... other props
175
+ />
176
+ ```
177
+
178
+ ### Permission-Based Editing
179
+ ```javascript
180
+ <GoalImageGallery
181
+ imageCodes={images}
182
+ canEdit={hasPermission('EDIT_IMAGES')}
183
+ permission="EDIT_IMAGES"
184
+ // ... other props
185
+ />
186
+ ```
187
+
188
+ ### Custom Upload Folder
189
+ ```javascript
190
+ const handleUpload = async (imageData) => {
191
+ return await api.uploadImage({
192
+ ...imageData,
193
+ folder: 'custom-folder',
194
+ application: 'MY_APP'
195
+ });
196
+ };
197
+ ```
198
+
199
+ ## Browser Support
200
+
201
+ - βœ… Chrome/Edge (full support)
202
+ - βœ… Firefox (full support)
203
+ - βœ… Safari (full support)
204
+ - ⚠️ IE11 (limited, no clipboard)
205
+ - βœ… Mobile browsers (optimized)
206
+
207
+ ## Performance Tips
208
+
209
+ 1. Use thumbnail versions for gallery
210
+ 2. Implement pagination for large sets
211
+ 3. Compress images before upload
212
+ 4. Use lazy loading for images
213
+ 5. Cleanup object URLs properly
214
+
215
+ ## Troubleshooting
216
+
217
+ **Images not loading?**
218
+ - Check image URLs
219
+ - Verify permissions
220
+ - Check network connectivity
221
+
222
+ **Upload not working?**
223
+ - Verify API handler
224
+ - Check file size limits
225
+ - Validate file formats
226
+
227
+ **Clipboard paste not working?**
228
+ - Ensure HTTPS
229
+ - Check browser support
230
+ - Verify permissions
231
+
232
+ **Poor performance?**
233
+ - Reduce image sizes
234
+ - Use pagination
235
+ - Implement virtual scrolling
package/README.md ADDED
@@ -0,0 +1,479 @@
1
+ # GoalImageGallery Component Documentation
2
+
3
+ ## Overview
4
+
5
+ The `GoalImageGallery` is a modern, feature-rich image gallery component for the Goal application. It provides a comprehensive solution for displaying, managing, and uploading images with advanced UI/UX features and accessibility support.
6
+
7
+ ## Key Features
8
+
9
+ ### πŸ–ΌοΈ **Multi-Method Image Upload**
10
+ - **File Upload**: Traditional file selection with drag-and-drop support
11
+ - **Clipboard Paste**: Paste images directly from clipboard using Ctrl+V
12
+ - **URL Loading**: Load images from remote URLs
13
+
14
+ ### 🎨 **Modern UI/UX**
15
+ - Responsive grid layout that adapts to screen size
16
+ - Smooth hover effects and transitions
17
+ - Material Design 3 styling
18
+ - Dark/light theme support
19
+ - Loading states and skeleton animations
20
+
21
+ ### πŸ” **Advanced Image Viewer**
22
+ - Full-screen modal viewer
23
+ - Zoom controls (0.5x to 3x)
24
+ - Image navigation (previous/next)
25
+ - Keyboard navigation support
26
+ - Download functionality
27
+
28
+ ### β™Ώ **Accessibility**
29
+ - ARIA labels and roles
30
+ - Keyboard navigation
31
+ - Screen reader support
32
+ - High contrast mode compatibility
33
+ - Focus management
34
+
35
+ ### πŸ“± **Mobile Responsive**
36
+ - Touch-friendly interface
37
+ - Optimized for mobile devices
38
+ - Swipe gestures support
39
+ - Responsive breakpoints
40
+
41
+ ## Installation
42
+
43
+ ```javascript
44
+ import GoalImageGallery from './components/common/goal-image-gallery';
45
+ ```
46
+
47
+ ## Basic Usage
48
+
49
+ ### Simple Gallery
50
+ ```javascript
51
+ <GoalImageGallery
52
+ imageCodes={['img1', 'img2', 'img3']}
53
+ canEdit={false}
54
+ />
55
+ ```
56
+
57
+ ### Editable Gallery
58
+ ```javascript
59
+ <GoalImageGallery
60
+ imageCodes={imageCodes}
61
+ canEdit={true}
62
+ ownerEntity={{ id: 'product-123' }}
63
+ imageHandlerApi={handleImageUpload}
64
+ afterUpload={refreshImages}
65
+ multiple={true}
66
+ />
67
+ ```
68
+
69
+ ### Advanced Configuration
70
+ ```javascript
71
+ <GoalImageGallery
72
+ imageCodes={imageCodes}
73
+ canEdit={true}
74
+ ownerEntity={{ id: 'product-123', type: 'product' }}
75
+ imageHandlerApi={handleImageUpload}
76
+ afterUpload={refreshImages}
77
+ multiple={true}
78
+ permission="EDIT_IMAGES"
79
+ emptyMessage="No product images available"
80
+ showImageInfo={true}
81
+ allowDownload={true}
82
+ />
83
+ ```
84
+
85
+ ## Props
86
+
87
+ | Prop | Type | Default | Description |
88
+ |------|------|---------|-------------|
89
+ | `canEdit` | `boolean` | `false` | Enable editing capabilities |
90
+ | `ownerEntity` | `object` | - | Entity that owns the images |
91
+ | `imageHandlerApi` | `function` | - | API function for image operations |
92
+ | `afterUpload` | `function` | - | Callback after successful upload |
93
+ | `imageCodes` | `string \| array` | - | Image codes to display |
94
+ | `multiple` | `boolean` | `false` | Allow multiple image selection |
95
+ | `permission` | `string` | - | Required permission for editing |
96
+ | `emptyMessage` | `string` | `'No hay imΓ‘genes para mostrar'` | Message shown when no images |
97
+ | `showImageInfo` | `boolean` | `false` | Show image information overlay |
98
+ | `allowDownload` | `boolean` | `true` | Enable download functionality |
99
+
100
+ ## Upload Methods
101
+
102
+ ### 1. File Upload
103
+ Users can upload images by:
104
+ - Clicking the "Add Image" button
105
+ - Dragging and dropping files onto the gallery
106
+ - Using the file selection dialog
107
+
108
+ **Supported formats**: JPEG, PNG, GIF, WebP
109
+ **Maximum file size**: 25MB (configurable)
110
+
111
+ ### 2. Clipboard Paste
112
+ Users can paste images directly from the clipboard:
113
+ - Copy an image from any source (screenshot, browser, etc.)
114
+ - Press `Ctrl+V` anywhere in the gallery
115
+ - The image will be automatically processed and uploaded
116
+
117
+ **Note**: Clipboard functionality requires modern browser support
118
+
119
+ ### 3. URL Loading
120
+ Users can load images from URLs:
121
+ - Enter a direct image URL
122
+ - The component validates the URL and loads the image
123
+ - Supports all standard image formats
124
+
125
+ ## Keyboard Shortcuts
126
+
127
+ ### Image Viewer
128
+ - `←` / `β†’`: Navigate between images
129
+ - `+` / `=`: Zoom in
130
+ - `-`: Zoom out
131
+ - `Escape`: Close image viewer
132
+
133
+ ### Gallery Navigation
134
+ - `Tab`: Navigate between interactive elements
135
+ - `Enter` / `Space`: Activate buttons
136
+ - `Escape`: Close dialogs
137
+
138
+ ## API Integration
139
+
140
+ The component requires an `imageHandlerApi` function that handles image operations:
141
+
142
+ ```javascript
143
+ const handleImageUpload = async (imageData) => {
144
+ try {
145
+ const response = await api.uploadImages({
146
+ ...imageData,
147
+ companyId: currentCompany,
148
+ entityId: ownerEntity.id
149
+ });
150
+
151
+ return {
152
+ success: true,
153
+ data: response.data,
154
+ message: 'Images uploaded successfully'
155
+ };
156
+ } catch (error) {
157
+ return {
158
+ success: false,
159
+ message: error.message
160
+ };
161
+ }
162
+ };
163
+ ```
164
+
165
+ ## Styling and Theming
166
+
167
+ The component uses Material-UI's theming system and can be customized:
168
+
169
+ ```javascript
170
+ const theme = createTheme({
171
+ components: {
172
+ MuiCard: {
173
+ styleOverrides: {
174
+ root: {
175
+ // Custom card styles
176
+ }
177
+ }
178
+ }
179
+ }
180
+ });
181
+ ```
182
+
183
+ ## Performance Considerations
184
+
185
+ - **Image Optimization**: Uses thumbnail versions for gallery view
186
+ - **Lazy Loading**: Images are loaded on demand
187
+ - **Memory Management**: Proper cleanup of object URLs
188
+ - **Debounced Operations**: Prevents excessive API calls
189
+
190
+ ## Error Handling
191
+
192
+ The component provides comprehensive error handling:
193
+
194
+ - **Upload Errors**: File size, format, or network issues
195
+ - **Loading Errors**: Broken image URLs or network problems
196
+ - **Permission Errors**: Insufficient user permissions
197
+ - **Browser Compatibility**: Graceful degradation for older browsers
198
+
199
+ ## Browser Support
200
+
201
+ - **Modern Browsers**: Full feature support
202
+ - **Internet Explorer 11**: Limited support (no clipboard paste)
203
+ - **Mobile Browsers**: Optimized experience
204
+ - **Accessibility Tools**: Full compatibility
205
+
206
+ ## Examples
207
+
208
+ ### Product Gallery
209
+ ```javascript
210
+ <GoalImageGallery
211
+ imageCodes={product.images}
212
+ canEdit={hasPermission('EDIT_PRODUCTS')}
213
+ ownerEntity={{ id: product.id, type: 'product' }}
214
+ imageHandlerApi={productImageApi.upload}
215
+ afterUpload={refreshProduct}
216
+ multiple={true}
217
+ emptyMessage="No product images available"
218
+ showImageInfo={true}
219
+ />
220
+ ```
221
+
222
+ ### User Avatar
223
+ ```javascript
224
+ <GoalImageGallery
225
+ imageCodes={user.avatar}
226
+ canEdit={isOwner}
227
+ ownerEntity={{ id: user.id, type: 'user' }}
228
+ imageHandlerApi={userImageApi.upload}
229
+ afterUpload={refreshUser}
230
+ multiple={false}
231
+ emptyMessage="No avatar set"
232
+ showImageInfo={false}
233
+ />
234
+ ```
235
+
236
+ ### Document Gallery
237
+ ```javascript
238
+ <GoalImageGallery
239
+ imageCodes={document.attachments}
240
+ canEdit={canEditDocument}
241
+ ownerEntity={{ id: document.id, type: 'document' }}
242
+ imageHandlerApi={documentImageApi.upload}
243
+ afterUpload={refreshDocument}
244
+ multiple={true}
245
+ permission="EDIT_DOCUMENTS"
246
+ allowDownload={true}
247
+ />
248
+ ```
249
+
250
+ ## Best Practices
251
+
252
+ 1. **Performance**: Use thumbnail versions for gallery display
253
+ 2. **Accessibility**: Always provide meaningful alt text
254
+ 3. **Error Handling**: Implement comprehensive error handling
255
+ 4. **Permissions**: Check user permissions before enabling editing
256
+ 5. **Validation**: Validate file types and sizes on both client and server
257
+ 6. **Responsive Design**: Test on various screen sizes
258
+ 7. **Loading States**: Provide visual feedback during operations
259
+
260
+ ## Troubleshooting
261
+
262
+ ### Common Issues
263
+
264
+ **Issue**: Images not loading
265
+ - **Solution**: Check image URLs and permissions
266
+
267
+ **Issue**: Upload not working
268
+ - **Solution**: Verify `imageHandlerApi` is properly configured
269
+
270
+ **Issue**: Clipboard paste not working
271
+ - **Solution**: Ensure HTTPS and modern browser support
272
+
273
+ **Issue**: Poor performance with many images
274
+ - **Solution**: Implement pagination or virtual scrolling
275
+
276
+ ### Debug Mode
277
+
278
+ Enable debug mode for development:
279
+
280
+ ```javascript
281
+ <GoalImageGallery
282
+ // ... other props
283
+ debug={process.env.NODE_ENV === 'development'}
284
+ />
285
+ ```
286
+
287
+ ## Migration Guide
288
+
289
+ ### From CommonImageGallery
290
+
291
+ ```javascript
292
+ // Old
293
+ <CommonImageGallery
294
+ photos={photos}
295
+ canEdit={canEdit}
296
+ onSelectImage={handleSelect}
297
+ />
298
+
299
+ // New
300
+ <GoalImageGallery
301
+ imageCodes={imageCodes}
302
+ canEdit={canEdit}
303
+ ownerEntity={ownerEntity}
304
+ imageHandlerApi={imageApi}
305
+ afterUpload={handleUpload}
306
+ />
307
+ ```
308
+
309
+ ### From Basic Image Display
310
+
311
+ ```javascript
312
+ // Old
313
+ {images.map(img => (
314
+ <img key={img.id} src={img.url} alt={img.title} />
315
+ ))}
316
+
317
+ // New
318
+ <GoalImageGallery
319
+ imageCodes={images.map(img => img.code)}
320
+ canEdit={false}
321
+ />
322
+ ```
323
+
324
+ ## Contributing
325
+
326
+ When contributing to this component:
327
+
328
+ 1. Follow the existing code style
329
+ 2. Add tests for new features
330
+ 3. Update documentation
331
+ 4. Test accessibility features
332
+ 5. Verify mobile responsiveness
333
+
334
+ ## License
335
+
336
+ This component is part of the Goal application and follows the project's licensing terms.
337
+
338
+ ## πŸ—οΈ **Modular Architecture**
339
+
340
+ The component has been fully modularized for better maintainability and reusability:
341
+
342
+ ### Component Structure
343
+
344
+ ```
345
+ goal-image-gallery/
346
+ β”œβ”€β”€ index.js # Main exports
347
+ β”œβ”€β”€ GoalImageGallery.js # Main component
348
+ β”œβ”€β”€ components/ # Modular sub-components
349
+ β”‚ β”œβ”€β”€ ImageGalleryGrid.js
350
+ β”‚ β”œβ”€β”€ ImageGalleryModal.js
351
+ β”‚ β”œβ”€β”€ ImageGalleryItem.js
352
+ β”‚ └── ImageGalleryEmptyState.js
353
+ β”œβ”€β”€ hooks/ # Custom hooks
354
+ β”‚ └── use-image-gallery.js
355
+ β”œβ”€β”€ styles/ # Styled components
356
+ β”‚ └── styled-components.js
357
+ β”œβ”€β”€ utils/ # Utility functions
358
+ β”‚ └── image-utils.js
359
+ └── docs/ # Documentation
360
+ β”œβ”€β”€ README.md
361
+ β”œβ”€β”€ QUICK_REFERENCE.md
362
+ β”œβ”€β”€ MIGRATION.md
363
+ └── examples.js
364
+ ```
365
+
366
+ ### Available Exports
367
+
368
+ #### Main Component
369
+ ```javascript
370
+ import { GoalImageGallery } from '@goal/components/common/goal-image-gallery';
371
+ ```
372
+
373
+ #### Sub-components
374
+ ```javascript
375
+ import {
376
+ ImageGalleryGrid,
377
+ ImageGalleryModal,
378
+ ImageGalleryItem,
379
+ ImageGalleryEmptyState
380
+ } from '@goal/components/common/goal-image-gallery';
381
+ ```
382
+
383
+ #### Custom Hooks
384
+ ```javascript
385
+ import {
386
+ useImageGallery,
387
+ useImageZoom,
388
+ useClipboard,
389
+ useKeyboardNavigation
390
+ } from '@goal/components/common/goal-image-gallery';
391
+ ```
392
+
393
+ #### Styled Components
394
+ ```javascript
395
+ import {
396
+ StyledImageContainer,
397
+ ImageOverlay,
398
+ StyledModalContainer
399
+ } from '@goal/components/common/goal-image-gallery';
400
+ ```
401
+
402
+ #### Utility Functions
403
+ ```javascript
404
+ import {
405
+ handleImageError,
406
+ downloadImage,
407
+ processImageCodes,
408
+ getGridColumns,
409
+ isValidImageFile,
410
+ formatFileSize
411
+ } from '@goal/components/common/goal-image-gallery';
412
+ ```
413
+
414
+ ### Using Individual Components
415
+
416
+ ```javascript
417
+ import {
418
+ ImageGalleryGrid,
419
+ ImageGalleryModal,
420
+ useImageGallery
421
+ } from '@goal/components/common/goal-image-gallery';
422
+
423
+ function CustomGallery() {
424
+ const { imageList, openImage, handleOpenImage } = useImageGallery({
425
+ imageCodes: ['image1', 'image2'],
426
+ multiple: true
427
+ });
428
+
429
+ return (
430
+ <>
431
+ <ImageGalleryGrid
432
+ imageList={imageList}
433
+ onImageClick={handleOpenImage}
434
+ emptyMessage="No images"
435
+ />
436
+ <ImageGalleryModal
437
+ open={openImage !== null}
438
+ imageUrl={openImage}
439
+ imageList={imageList}
440
+ onClose={() => handleOpenImage(null)}
441
+ />
442
+ </>
443
+ );
444
+ }
445
+ ```
446
+
447
+ ## πŸ“¦ **Independent Package**
448
+
449
+ The component is now ready for export as an independent package:
450
+
451
+ ```json
452
+ {
453
+ "name": "@goal/image-gallery",
454
+ "version": "1.0.0",
455
+ "description": "Enhanced, modular image gallery component for React applications",
456
+ "main": "index.js",
457
+ "module": "index.js",
458
+ "types": "index.d.ts"
459
+ }
460
+ ```
461
+
462
+ ### TypeScript Support
463
+
464
+ Full TypeScript definitions are included:
465
+
466
+ ```typescript
467
+ interface GoalImageGalleryProps {
468
+ canEdit?: boolean;
469
+ ownerEntity?: object;
470
+ imageHandlerApi?: (data: any) => Promise<any>;
471
+ afterUpload?: (result: any) => void;
472
+ imageCodes?: string | string[];
473
+ multiple?: boolean;
474
+ permission?: string;
475
+ emptyMessage?: string;
476
+ showImageInfo?: boolean;
477
+ allowDownload?: boolean;
478
+ }
479
+ ```