@yogiswara/honcho-editor-ui 2.5.10 → 2.6.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.
Files changed (50) hide show
  1. package/dist/components/editor/HBulkPreset.js +12 -2
  2. package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +3 -0
  3. package/dist/hooks/demo/HonchoEditorBulkDemo.js +228 -0
  4. package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +3 -0
  5. package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +354 -0
  6. package/dist/hooks/demo/index.d.ts +2 -0
  7. package/dist/hooks/demo/index.js +2 -0
  8. package/dist/hooks/editor/type.d.ts +71 -0
  9. package/dist/hooks/editor/useHonchoEditorBulk.d.ts +10 -12
  10. package/dist/hooks/editor/useHonchoEditorBulk.js +126 -10
  11. package/dist/hooks/editor/useHonchoEditorSingle.d.ts +43 -0
  12. package/dist/hooks/editor/useHonchoEditorSingle.js +158 -0
  13. package/dist/hooks/useAdjustmentHistory.d.ts +9 -5
  14. package/dist/hooks/useAdjustmentHistory.js +187 -31
  15. package/dist/hooks/useAdjustmentHistoryBatch.d.ts +18 -1
  16. package/dist/hooks/useAdjustmentHistoryBatch.js +627 -201
  17. package/dist/hooks/useGallerySwipe.d.ts +1 -1
  18. package/dist/hooks/usePaging.d.ts +1 -1
  19. package/dist/hooks/usePaging.js +1 -1
  20. package/dist/hooks/usePreset.d.ts +1 -1
  21. package/dist/hooks/usePreset.js +35 -35
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.js +1 -1
  24. package/dist/lib/context/EditorContext.d.ts +10 -0
  25. package/dist/lib/context/EditorContext.js +4 -2
  26. package/dist/lib/hooks/useEditorHeadless.d.ts +18 -2
  27. package/dist/lib/hooks/useEditorHeadless.js +142 -63
  28. package/dist/utils/adjustment.d.ts +2 -1
  29. package/dist/utils/adjustment.js +16 -0
  30. package/dist/utils/imageLoader.d.ts +11 -0
  31. package/dist/utils/imageLoader.js +53 -0
  32. package/package.json +1 -1
  33. package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.d.ts +0 -17
  34. package/dist/components/editor/GalleryAlbum/SimplifiedAlbumGallery.js +0 -14
  35. package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.d.ts +0 -8
  36. package/dist/components/editor/GalleryAlbum/SimplifiedImageItem.js +0 -30
  37. package/dist/components/editor/HImageEditorPage.d.ts +0 -1
  38. package/dist/components/editor/HImageEditorPage.js +0 -187
  39. package/dist/hooks/__tests__/useGallerySwipe.test.d.ts +0 -0
  40. package/dist/hooks/__tests__/useGallerySwipe.test.js +0 -619
  41. package/dist/hooks/editor/useHonchoEditor.d.ts +0 -203
  42. package/dist/hooks/editor/useHonchoEditor.js +0 -716
  43. package/dist/hooks/useAdjustmentHistory.demo.d.ts +0 -8
  44. package/dist/hooks/useAdjustmentHistory.demo.js +0 -106
  45. package/dist/hooks/useAdjustmentHistory.example.d.ts +0 -38
  46. package/dist/hooks/useAdjustmentHistory.example.js +0 -182
  47. package/dist/hooks/useAdjustmentHistory.syncDemo.d.ts +0 -8
  48. package/dist/hooks/useAdjustmentHistory.syncDemo.js +0 -180
  49. package/dist/hooks/useGallerySwipe.example.d.ts +0 -24
  50. package/dist/hooks/useGallerySwipe.example.js +0 -184
@@ -21,13 +21,23 @@ export default function HBulkPreset(props) {
21
21
  return (_jsx(CardMedia, { component: "img", image: isExpanded ? "/v1/svg/expand-editor.svg" : "/v1/svg/expanded-editor.svg", sx: { width: "11.67px", height: "5.83px", right: '14px', position: 'absolute', pointerEvents: 'none' } }));
22
22
  };
23
23
  return (_jsx(_Fragment, { children: _jsx(Stack, { children: _jsxs(Accordion, { sx: accordionStyle, expanded: isPanelExpanded('preset'), onChange: props.onPanelChange('preset'), disableGutters: true, children: [_jsx(AccordionSummary, { sx: { pr: 0 }, children: _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { width: '100%' }, children: [_jsx(Typography, { sx: { ...typography.titleMedium, color: colors.surface }, children: "Preset" }), _jsx(CardMedia, { component: "img", image: isPanelExpanded('preset') ? "/v1/svg/expanded-editor.svg" : "/v1/svg/expand-editor.svg", sx: { width: "11.67px", height: "5.83px" } })] }) }), _jsx(AccordionDetails, { sx: { pr: "4px" }, children: _jsx(FormControl, { fullWidth: true, children: _jsxs(Select, { fullWidth: true, value: props.selectedPreset, onChange: props.onSelectPreset, IconComponent: CustomSelectIcon, renderValue: (selectedId) => {
24
+ // Handle empty selection case
25
+ if (!selectedId) {
26
+ return _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, opacity: 0.7 }, children: "Select Preset" });
27
+ }
24
28
  // Uses props.presets to find the name
25
29
  const selectedPresetObject = props.presets.find(p => p.id === selectedId);
26
30
  if (!selectedPresetObject) {
27
- return _jsx(Typography, { sx: { ...typography.bodyMedium }, children: "Select" });
31
+ return _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, opacity: 0.7 }, children: "Select Preset" });
28
32
  }
29
33
  return _jsx(Typography, { sx: { ...typography.bodyMedium }, children: selectedPresetObject.name });
30
34
  }, MenuProps: {
31
35
  slotProps: { paper: { sx: { backgroundColor: colors.onBackground, color: colors.surface, border: `1px solid ${colors.onSurfaceVariant1}`, mt: '20px', width: '178px', boxShadow: 'none' } } }
32
- }, sx: { border: `1px solid ${colors.outlineVariant}`, height: '44px', width: '215px', boxShadow: 'none' }, children: [props.presets.map((preset) => (_jsx(MenuItem, { value: preset.id, sx: { borderRadius: '4px', py: '4px', my: '0px', px: '0px', mx: '0px' }, children: _jsxs(Stack, { direction: "row", justifyContent: "space-around", alignItems: "center", sx: { width: '100%', py: '0px', px: '0px', mx: '0px', my: '4px' }, children: [_jsx(CardMedia, { component: "img", image: "v1/svg/check-ratio-editor.svg", sx: { width: "20px", height: "20px", mr: '-16px', px: '0px', visibility: props.selectedPreset === preset.id ? 'visible' : 'hidden' } }), _jsx(Typography, { sx: { width: '24px', textWrap: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', display: 'block', color: colors.surface, pr: "82px", pl: "0px", ml: "0px", justifyContent: 'flex-start', ...typography.bodyMedium }, children: preset.name }), _jsx(IconButton, { "aria-label": `Options for ${preset.name}`, onClick: (event) => props.onPresetMenuClick(event, preset.id), sx: { padding: "0px", margin: "0px", mr: "0px" }, children: _jsx(CardMedia, { component: "img", image: "/v1/svg/dots-editor.svg", alt: "Options", sx: { width: '20px', height: '20px' } }) })] }) }, preset.id))), _jsx(Box, { sx: { px: '16px', my: '8px' }, children: _jsx(Button, { fullWidth: true, variant: "outlined", sx: { ...typography.labelMedium, height: '40px', color: colors.onBackground, backgroundColor: colors.surface, borderRadius: '100px', borderColor: colors.surface, textTransform: 'none', '&:hover': { backgroundColor: '#e0e0e0', borderColor: colors.surface } }, onClick: props.onOpenPresetModal, children: "Create Preset" }) })] }) }) })] }) }) }));
36
+ }, sx: { border: `1px solid ${colors.outlineVariant}`, height: '44px', width: '215px', boxShadow: 'none' }, children: [_jsx(MenuItem, { value: "", sx: { borderRadius: '4px', py: '4px', my: '0px', px: '0px', mx: '0px' }, children: _jsx(Stack, { direction: "row", justifyContent: "center", alignItems: "center", sx: { width: '100%', py: '0px', px: '0px', mx: '0px', my: '4px' }, children: _jsx(Typography, { sx: {
37
+ width: '100%',
38
+ textAlign: 'center',
39
+ color: colors.surface,
40
+ opacity: 0.7,
41
+ ...typography.bodyMedium
42
+ }, children: "No Preset" }) }) }), props.presets.map((preset) => (_jsx(MenuItem, { value: preset.id, sx: { borderRadius: '4px', py: '4px', my: '0px', px: '0px', mx: '0px' }, children: _jsxs(Stack, { direction: "row", justifyContent: "space-around", alignItems: "center", sx: { width: '100%', py: '0px', px: '0px', mx: '0px', my: '4px' }, children: [_jsx(CardMedia, { component: "img", image: "v1/svg/check-ratio-editor.svg", sx: { width: "20px", height: "20px", mr: '-16px', px: '0px', visibility: props.selectedPreset === preset.id ? 'visible' : 'hidden' } }), _jsx(Typography, { sx: { width: '24px', textWrap: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', display: 'block', color: colors.surface, pr: "82px", pl: "0px", ml: "0px", justifyContent: 'flex-start', ...typography.bodyMedium }, children: preset.name }), _jsx(IconButton, { "aria-label": `Options for ${preset.name}`, onClick: (event) => props.onPresetMenuClick(event, preset.id), sx: { padding: "0px", margin: "0px", mr: "0px" }, children: _jsx(CardMedia, { component: "img", image: "/v1/svg/dots-editor.svg", alt: "Options", sx: { width: '20px', height: '20px' } }) })] }) }, preset.id))), _jsx(Box, { sx: { px: '16px', my: '8px' }, children: _jsx(Button, { fullWidth: true, variant: "outlined", sx: { ...typography.labelMedium, height: '40px', color: colors.onBackground, backgroundColor: colors.surface, borderRadius: '100px', borderColor: colors.surface, textTransform: 'none', '&:hover': { backgroundColor: '#e0e0e0', borderColor: colors.surface } }, onClick: props.onOpenPresetModal, children: "Create Preset" }) })] }) }) })] }) }) }));
33
43
  }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const HonchoEditorBulkDemo: React.FC;
3
+ export default HonchoEditorBulkDemo;
@@ -0,0 +1,228 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useState } from 'react';
3
+ import { Box, Container, Typography, Button, Grid, Card, CardMedia, CardContent, Checkbox, Chip, Alert, CircularProgress, ButtonGroup, Paper, Divider, FormControl, InputLabel, Select, MenuItem, Stack } from '@mui/material';
4
+ import { useHonchoEditorBulk } from '../editor/useHonchoEditorBulk';
5
+ // Mock data for demonstration
6
+ const createMockGallery = (id, adjustments) => ({
7
+ id,
8
+ uid: 'demo-user',
9
+ event_id: 'demo-event',
10
+ download: {
11
+ key: `${id}-download`,
12
+ path: `https://picsum.photos/800/600?random=${id}`,
13
+ size: 1024000,
14
+ width: 800,
15
+ height: 600,
16
+ },
17
+ download_edited: {
18
+ key: `${id}-download-edited`,
19
+ path: `https://picsum.photos/800/600?random=${id}`,
20
+ size: 1024000,
21
+ width: 800,
22
+ height: 600,
23
+ },
24
+ thumbnail: {
25
+ key: `${id}-thumb`,
26
+ path: `https://picsum.photos/300/200?random=${id}`,
27
+ size: 50000,
28
+ width: 300,
29
+ height: 200,
30
+ },
31
+ thumbnail_edited: {
32
+ key: `${id}-thumb-edited`,
33
+ path: `https://picsum.photos/300/200?random=${id}`,
34
+ size: 50000,
35
+ width: 300,
36
+ height: 200,
37
+ },
38
+ is_original: true,
39
+ available: true,
40
+ show_gallery: true,
41
+ editor_config: {
42
+ color_adjustment: {
43
+ temperature: adjustments?.tempScore || 0,
44
+ tint: adjustments?.tintScore || 0,
45
+ vibrance: adjustments?.vibranceScore || 0,
46
+ saturation: adjustments?.saturationScore || 0,
47
+ exposure: adjustments?.exposureScore || 0,
48
+ highlights: adjustments?.highlightsScore || 0,
49
+ shadows: adjustments?.shadowsScore || 0,
50
+ whites: adjustments?.whitesScore || 0,
51
+ blacks: adjustments?.blacksScore || 0,
52
+ contrast: adjustments?.contrastScore || 0,
53
+ clarity: adjustments?.clarityScore || 0,
54
+ sharpness: adjustments?.sharpnessScore || 0,
55
+ },
56
+ transformation_adjustment: [],
57
+ watermarks: [],
58
+ },
59
+ log: {
60
+ created_at: new Date().toISOString(),
61
+ updated_at: new Date().toISOString(),
62
+ },
63
+ });
64
+ // Mock Controller implementation
65
+ const createMockController = () => {
66
+ const mockImages = [
67
+ createMockGallery('1', { tempScore: 5, exposureScore: 2 }),
68
+ createMockGallery('2'),
69
+ createMockGallery('3', { contrastScore: -3, clarityScore: 8 }),
70
+ createMockGallery('4'),
71
+ createMockGallery('5', { vibranceScore: 10 }),
72
+ createMockGallery('6'),
73
+ createMockGallery('7', { tempScore: -8, tintScore: 4 }),
74
+ createMockGallery('8'),
75
+ createMockGallery('9'),
76
+ createMockGallery('10'),
77
+ ];
78
+ return {
79
+ onGetImage: async (uid, imageId) => {
80
+ await new Promise(resolve => setTimeout(resolve, 500));
81
+ const image = mockImages.find(img => img.id === imageId);
82
+ if (!image)
83
+ throw new Error(`Image ${imageId} not found`);
84
+ return image;
85
+ },
86
+ getImageList: async (uid, eventId, page) => {
87
+ await new Promise(resolve => setTimeout(resolve, 800));
88
+ const pageSize = 4;
89
+ const startIndex = (page - 1) * pageSize;
90
+ const endIndex = startIndex + pageSize;
91
+ const pageImages = mockImages.slice(startIndex, endIndex);
92
+ return {
93
+ gallery: pageImages,
94
+ limit: pageSize,
95
+ current_page: page,
96
+ prev_page: page > 1 ? page - 1 : 0,
97
+ next_page: endIndex < mockImages.length ? page + 1 : 0,
98
+ sum_of_image: pageImages.length,
99
+ };
100
+ },
101
+ syncConfig: async (uid) => {
102
+ await new Promise(resolve => setTimeout(resolve, 200));
103
+ },
104
+ handleBack: (uid, imageId) => {
105
+ console.log(`Back to: ${imageId}`);
106
+ },
107
+ getPresets: async (uid) => {
108
+ return [
109
+ { id: '1', name: 'Warm Sunset', is_default: false, temperature: 15, tint: 5, saturation: 8, vibrance: 12, exposure: 2, contrast: 5, highlights: -10, shadows: 8, whites: 3, blacks: -5, clarity: 4, sharpness: 6 },
110
+ { id: '2', name: 'Cool Morning', is_default: false, temperature: -12, tint: -3, saturation: -2, vibrance: 5, exposure: 1, contrast: 3, highlights: -5, shadows: 12, whites: 8, blacks: -8, clarity: 6, sharpness: 4 },
111
+ { id: '3', name: 'High Contrast', is_default: false, temperature: 0, tint: 0, saturation: 5, vibrance: 8, exposure: 0, contrast: 20, highlights: -15, shadows: 15, whites: 10, blacks: -10, clarity: 15, sharpness: 8 },
112
+ ];
113
+ },
114
+ createPreset: async (uid, name, settings) => {
115
+ console.log(`Creating preset: ${name}`, settings);
116
+ },
117
+ deletePreset: async (uid, presetId) => {
118
+ console.log(`Deleting preset: ${presetId}`);
119
+ },
120
+ updatePreset: async (uid, data) => {
121
+ console.log(`Updating preset:`, data);
122
+ },
123
+ createEditorConfig: async (uid, payload) => {
124
+ await new Promise(resolve => setTimeout(resolve, 300));
125
+ console.log('Creating editor config:', payload);
126
+ },
127
+ getEditorHistory: async (uid, imageId) => {
128
+ await new Promise(resolve => setTimeout(resolve, 200));
129
+ // Mock history response - return empty history for demo
130
+ return {
131
+ current_task_id: "",
132
+ history: []
133
+ };
134
+ },
135
+ getGalleryUpdateTimestamp: async (uid, eventId) => {
136
+ await new Promise(resolve => setTimeout(resolve, 100));
137
+ return {
138
+ gallery: []
139
+ };
140
+ },
141
+ setHistoryIndex: async (uid, imageId, taskId) => {
142
+ await new Promise(resolve => setTimeout(resolve, 100));
143
+ console.log(`Setting history index for image ${imageId} to task ${taskId}`);
144
+ },
145
+ };
146
+ };
147
+ const AdjustmentControls = ({ label, onDecreaseMax, onDecrease, onIncrease, onIncreaseMax, disabled = false }) => (_jsxs(Box, { mb: 2, children: [_jsx(Typography, { variant: "body2", gutterBottom: true, children: label }), _jsxs(ButtonGroup, { size: "small", variant: "outlined", children: [_jsx(Button, { onClick: onDecreaseMax, disabled: disabled, children: "--" }), _jsx(Button, { onClick: onDecrease, disabled: disabled, children: "-" }), _jsx(Button, { onClick: onIncrease, disabled: disabled, children: "+" }), _jsx(Button, { onClick: onIncreaseMax, disabled: disabled, children: "++" })] })] }));
148
+ export const HonchoEditorBulkDemo = () => {
149
+ const [controller] = useState(() => createMockController());
150
+ const [showAdjustments, setShowAdjustments] = useState(false);
151
+ const { imageData, isLoading, error, selectedIds, hasMore, selectedBulkPreset, presets, // Add presets
152
+ activePreset, // Add activePreset
153
+ handleToggleImageSelection, handleLoadMore, handleRefresh, handleSelectBulkPreset, handleBackCallbackBulk,
154
+ // Temperature adjustments
155
+ handleBulkTempDecreaseMax, handleBulkTempDecrease, handleBulkTempIncrease, handleBulkTempIncreaseMax,
156
+ // Tint adjustments
157
+ handleBulkTintDecreaseMax, handleBulkTintDecrease, handleBulkTintIncrease, handleBulkTintIncreaseMax,
158
+ // Exposure adjustments
159
+ handleBulkExposureDecreaseMax, handleBulkExposureDecrease, handleBulkExposureIncrease, handleBulkExposureIncreaseMax,
160
+ // Contrast adjustments
161
+ handleBulkContrastDecreaseMax, handleBulkContrastDecrease, handleBulkContrastIncrease, handleBulkContrastIncreaseMax,
162
+ // Clarity adjustments
163
+ handleBulkClarityDecreaseMax, handleBulkClarityDecrease, handleBulkClarityIncrease, handleBulkClarityIncreaseMax,
164
+ // History actions
165
+ handleUndo, handleRedo, handleReset, historyInfo, } = useHonchoEditorBulk(controller, 'demo-event', 'demo-user');
166
+ // Debug logging for preset state - less frequent
167
+ React.useEffect(() => {
168
+ const interval = setInterval(() => {
169
+ console.log('[HonchoEditorBulkDemo] Preset state:', {
170
+ presets: presets.map(p => ({ id: p.id, name: p.name })),
171
+ selectedBulkPreset,
172
+ activePreset: activePreset ? { id: activePreset.id, name: activePreset.name } : null,
173
+ selectedCount: selectedIds.length
174
+ });
175
+ }, 5000); // Every 5 seconds instead of on every render
176
+ return () => clearInterval(interval);
177
+ }, [presets, selectedBulkPreset, activePreset, selectedIds.length]);
178
+ const selectedCount = selectedIds.length;
179
+ const totalCount = imageData.length;
180
+ // Debug logging for presets
181
+ console.log('[HonchoEditorBulkDemo] Preset state:', {
182
+ presets: presets.map(p => ({ id: p.id, name: p.name })),
183
+ selectedBulkPreset,
184
+ activePreset: activePreset ? { id: activePreset.id, name: activePreset.name } : null,
185
+ selectedCount
186
+ });
187
+ const getAdjustmentSummary = (image) => {
188
+ const adjustments = [];
189
+ if (image.tempScore !== 0)
190
+ adjustments.push(`Temp: ${image.tempScore > 0 ? '+' : ''}${image.tempScore}`);
191
+ if (image.exposureScore !== 0)
192
+ adjustments.push(`Exp: ${image.exposureScore > 0 ? '+' : ''}${image.exposureScore}`);
193
+ if (image.contrastScore !== 0)
194
+ adjustments.push(`Con: ${image.contrastScore > 0 ? '+' : ''}${image.contrastScore}`);
195
+ if (image.clarityScore !== 0)
196
+ adjustments.push(`Cla: ${image.clarityScore > 0 ? '+' : ''}${image.clarityScore}`);
197
+ if (image.vibranceScore !== 0)
198
+ adjustments.push(`Vib: ${image.vibranceScore > 0 ? '+' : ''}${image.vibranceScore}`);
199
+ return adjustments;
200
+ };
201
+ return (_jsxs(Container, { maxWidth: "xl", sx: { py: 4 }, children: [_jsx(Typography, { variant: "h3", gutterBottom: true, align: "center", children: "Honcho Editor Bulk Demo" }), _jsx(Typography, { variant: "subtitle1", align: "center", color: "text.secondary", gutterBottom: true, children: "This demo shows the useHonchoEditorBulk hook in action with mock data" }), error && (_jsx(Alert, { severity: "error", sx: { mb: 3 }, children: error })), _jsx(Paper, { sx: { p: 3, mb: 3 }, children: _jsxs(Stack, { direction: "row", spacing: 2, alignItems: "center", flexWrap: "wrap", children: [_jsx(Button, { variant: "contained", onClick: handleRefresh, disabled: isLoading, children: isLoading ? _jsx(CircularProgress, { size: 20 }) : 'Refresh Images' }), _jsxs(Button, { variant: "outlined", onClick: () => setShowAdjustments(!showAdjustments), children: [showAdjustments ? 'Hide' : 'Show', " Adjustments"] }), _jsx(Button, { variant: "outlined", onClick: () => {
202
+ console.log('Debug Info:', {
203
+ selectedIds,
204
+ selectedCount,
205
+ showAdjustments,
206
+ presets: presets.map(p => ({ id: p.id, name: p.name })),
207
+ selectedBulkPreset,
208
+ activePreset: activePreset ? { id: activePreset.id, name: activePreset.name } : null,
209
+ imageData: imageData.map(img => ({ key: img.key, isSelected: img.isSelected }))
210
+ });
211
+ }, children: "Debug Selection" }), _jsx(Button, { variant: "outlined", onClick: handleBackCallbackBulk, children: "Back" }), _jsx(Chip, { label: `${selectedCount} of ${totalCount} selected`, color: selectedCount > 0 ? "primary" : "default" }), hasMore && (_jsx(Button, { variant: "outlined", onClick: handleLoadMore, disabled: isLoading, children: "Load More" })), _jsxs(FormControl, { size: "small", sx: { minWidth: 150 }, children: [_jsx(InputLabel, { children: "Bulk Preset" }), _jsxs(Select, { value: selectedBulkPreset, onChange: handleSelectBulkPreset, label: "Bulk Preset", displayEmpty: true, children: [_jsx(MenuItem, { value: "", children: _jsx("em", { children: "No Preset" }) }), presets.map((preset) => (_jsxs(MenuItem, { value: preset.id, children: [preset.name, activePreset?.id === preset.id && ' ✓'] }, preset.id)))] })] }), _jsxs(Typography, { variant: "body2", sx: { ml: 2, opacity: 0.7 }, children: ["Active: ", activePreset ? activePreset.name : 'None', " | Presets: ", presets.length] })] }) }), showAdjustments && (_jsxs(Paper, { sx: { p: 3, mb: 3 }, children: [_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { mb: 2 }, children: [_jsxs(Typography, { variant: "h6", children: ["Bulk Adjustments (", selectedCount, " images selected)"] }), _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(Button, { variant: "outlined", size: "small", onClick: handleUndo, disabled: !historyInfo.canUndo, sx: { minWidth: 80 }, children: "Undo" }), _jsx(Button, { variant: "outlined", size: "small", onClick: handleRedo, disabled: !historyInfo.canRedo, sx: { minWidth: 80 }, children: "Redo" }), _jsx(Button, { variant: "outlined", size: "small", onClick: () => handleReset(), disabled: selectedCount === 0, color: "warning", sx: { minWidth: 80 }, children: "Reset" })] })] }), selectedCount === 0 && (_jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: "Select one or more images below to enable bulk adjustments" })), _jsxs(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: ["History: ", historyInfo.currentIndex + 1, "/", historyInfo.totalStates, " states | Can Undo: ", historyInfo.canUndo ? 'Yes' : 'No', " | Can Redo: ", historyInfo.canRedo ? 'Yes' : 'No'] }), _jsxs(Grid, { container: true, spacing: 3, children: [_jsxs(Grid, { item: true, xs: 12, md: 3, children: [_jsx(Typography, { variant: "subtitle2", gutterBottom: true, children: "Color" }), _jsx(AdjustmentControls, { label: "Temperature", onDecreaseMax: handleBulkTempDecreaseMax, onDecrease: handleBulkTempDecrease, onIncrease: handleBulkTempIncrease, onIncreaseMax: handleBulkTempIncreaseMax, disabled: selectedCount === 0 }), _jsx(AdjustmentControls, { label: "Tint", onDecreaseMax: handleBulkTintDecreaseMax, onDecrease: handleBulkTintDecrease, onIncrease: handleBulkTintIncrease, onIncreaseMax: handleBulkTintIncreaseMax, disabled: selectedCount === 0 })] }), _jsxs(Grid, { item: true, xs: 12, md: 3, children: [_jsx(Typography, { variant: "subtitle2", gutterBottom: true, children: "Light" }), _jsx(AdjustmentControls, { label: "Exposure", onDecreaseMax: handleBulkExposureDecreaseMax, onDecrease: handleBulkExposureDecrease, onIncrease: handleBulkExposureIncrease, onIncreaseMax: handleBulkExposureIncreaseMax, disabled: selectedCount === 0 }), _jsx(AdjustmentControls, { label: "Contrast", onDecreaseMax: handleBulkContrastDecreaseMax, onDecrease: handleBulkContrastDecrease, onIncrease: handleBulkContrastIncrease, onIncreaseMax: handleBulkContrastIncreaseMax, disabled: selectedCount === 0 })] }), _jsxs(Grid, { item: true, xs: 12, md: 3, children: [_jsx(Typography, { variant: "subtitle2", gutterBottom: true, children: "Details" }), _jsx(AdjustmentControls, { label: "Clarity", onDecreaseMax: handleBulkClarityDecreaseMax, onDecrease: handleBulkClarityDecrease, onIncrease: handleBulkClarityIncrease, onIncreaseMax: handleBulkClarityIncreaseMax, disabled: selectedCount === 0 })] })] })] })), _jsx(Grid, { container: true, spacing: 2, children: imageData.map((image) => {
212
+ const adjustments = getAdjustmentSummary(image);
213
+ return (_jsx(Grid, { item: true, xs: 12, sm: 6, md: 4, lg: 3, children: _jsxs(Card, { sx: {
214
+ border: image.isSelected ? 2 : 1,
215
+ borderColor: image.isSelected ? 'primary.main' : 'divider',
216
+ cursor: 'pointer',
217
+ transition: 'all 0.2s',
218
+ '&:hover': {
219
+ transform: 'translateY(-2px)',
220
+ boxShadow: 2,
221
+ }
222
+ }, onClick: () => handleToggleImageSelection(image.key), children: [_jsx(CardMedia, { component: "img", height: "200", image: image.src, alt: image.alt, sx: { objectFit: 'cover' } }), _jsxs(CardContent, { sx: { pb: 1 }, children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", children: [_jsxs(Typography, { variant: "body2", color: "text.secondary", children: ["Image ", image.key] }), _jsx(Checkbox, { checked: image.isSelected, size: "small", onClick: (e) => {
223
+ e.stopPropagation();
224
+ handleToggleImageSelection(image.key);
225
+ } })] }), adjustments.length > 0 && (_jsx(Box, { mt: 1, children: _jsx(Stack, { direction: "row", spacing: 0.5, flexWrap: "wrap", children: adjustments.map((adj, index) => (_jsx(Chip, { label: adj, size: "small", variant: "outlined", sx: { fontSize: '0.7rem', height: 20 } }, index))) }) }))] })] }) }, image.key));
226
+ }) }), isLoading && imageData.length === 0 && (_jsx(Box, { display: "flex", justifyContent: "center", py: 4, children: _jsx(CircularProgress, {}) })), _jsxs(Box, { mt: 4, children: [_jsx(Divider, {}), _jsx(Typography, { variant: "body2", color: "text.secondary", align: "center", sx: { mt: 2 }, children: "Demo Notes: This uses mock data and simulated API calls. Select images and try the bulk adjustment controls above." })] })] }));
227
+ };
228
+ export default HonchoEditorBulkDemo;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const HonchoEditorSingleCleanDemo: React.FC;
3
+ export default HonchoEditorSingleCleanDemo;