@yogiswara/honcho-editor-ui 3.3.4 → 3.4.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/dist/components/editor/GalleryAlbum/AlbumImageGallery.d.ts +14 -7
- package/dist/components/editor/GalleryAlbum/AlbumImageGallery.js +207 -5
- package/dist/components/editor/GalleryAlbum/ImageItemComponents.d.ts +25 -0
- package/dist/components/editor/GalleryAlbum/ImageItemComponents.js +179 -0
- package/dist/components/editor/GalleryAlbum/colorsGallery.d.ts +9 -0
- package/dist/components/editor/GalleryAlbum/colorsGallery.js +9 -0
- package/dist/components/editor/GalleryAlbum/svg/Tick.d.ts +2 -0
- package/dist/components/editor/GalleryAlbum/svg/Tick.js +6 -0
- package/dist/components/editor/HBulkAccordionColorAdjustment.js +1 -2
- package/dist/components/editor/HBulkAccordionColorAdjustmentColors.js +1 -1
- package/dist/components/editor/HBulkPreset.d.ts +3 -7
- package/dist/components/editor/HBulkPreset.js +21 -22
- package/dist/components/editor/HBulkPresetMobile.d.ts +2 -2
- package/dist/components/editor/HBulkPresetMobile.js +2 -2
- package/dist/components/editor/HImageEditorBulkMobile.d.ts +2 -2
- package/dist/hooks/demo/HonchoEditorBulkDemo.d.ts +0 -3
- package/dist/hooks/demo/HonchoEditorBulkDemo.js +770 -411
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.d.ts +0 -3
- package/dist/hooks/demo/HonchoEditorSingleCleanDemo.js +882 -354
- package/dist/hooks/demo/index.d.ts +0 -2
- package/dist/hooks/demo/index.js +3 -2
- package/dist/hooks/editor/type.d.ts +15 -13
- package/dist/hooks/editor/useHonchoEditorBulk.d.ts +47 -5
- package/dist/hooks/editor/useHonchoEditorBulk.js +252 -133
- package/dist/hooks/useAdjustmentHistory.js +12 -12
- package/dist/hooks/useAdjustmentHistoryBatch.d.ts +33 -31
- package/dist/hooks/useAdjustmentHistoryBatch.js +703 -170
- package/dist/hooks/usePreset.js +12 -12
- package/dist/index.d.ts +5 -7
- package/dist/index.js +5 -4
- package/dist/services/type.d.ts +14 -0
- package/dist/utils/adjustment.d.ts +1 -1
- package/dist/utils/adjustment.js +15 -14
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.js +11 -0
- package/package.json +4 -2
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { GallerySetup } from "../../../services/type";
|
|
2
|
+
interface ImageGalleryInfiniteProps {
|
|
3
|
+
imageCollection: GallerySetup[];
|
|
4
|
+
isSelectedMode?: boolean;
|
|
5
|
+
isHiddenGallery?: boolean;
|
|
6
|
+
isLoading?: boolean;
|
|
7
|
+
isLoadingMore?: boolean;
|
|
8
|
+
hasMore?: boolean;
|
|
9
|
+
onPreview?: (photo: GallerySetup) => () => void;
|
|
10
|
+
onSelectedMode?: () => void;
|
|
11
|
+
onToggleSelect?: (photo: GallerySetup) => () => void;
|
|
12
|
+
onLoadMore?: () => Promise<void>;
|
|
6
13
|
}
|
|
7
|
-
|
|
8
|
-
export
|
|
14
|
+
declare const AlbumImageGalleryInfinite: React.FC<ImageGalleryInfiniteProps>;
|
|
15
|
+
export default AlbumImageGalleryInfinite;
|
|
@@ -1,7 +1,209 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Box, useMediaQuery, CircularProgress } from "@mui/material";
|
|
4
|
+
import { memo, useCallback, useMemo, useRef, useEffect } from "react";
|
|
5
|
+
import { MasonryInfiniteGrid } from "@egjs/react-infinitegrid";
|
|
6
|
+
import ImageItemComponents from "./ImageItemComponents";
|
|
7
|
+
import useColors from '../../../themes/colors';
|
|
8
|
+
// Custom comparison function for ImageItem (reusing existing logic)
|
|
9
|
+
const imageItemPropsAreEqual = (prevProps, nextProps) => {
|
|
10
|
+
// Compare photo data deeply
|
|
11
|
+
const prevPhoto = prevProps.photo;
|
|
12
|
+
const nextPhoto = nextProps.photo;
|
|
13
|
+
const prevData = prevProps.data;
|
|
14
|
+
const nextData = nextProps.data;
|
|
15
|
+
// Check if photo key/ID is the same
|
|
16
|
+
if (prevPhoto.key !== nextPhoto.key)
|
|
17
|
+
return false;
|
|
18
|
+
// Check critical photo properties that affect rendering
|
|
19
|
+
if (prevData.isSelected !== nextData.isSelected)
|
|
20
|
+
return false;
|
|
21
|
+
if (JSON.stringify(prevData.adjustments) !== JSON.stringify(nextData.adjustments))
|
|
22
|
+
return false;
|
|
23
|
+
if (prevData.frame !== nextData.frame)
|
|
24
|
+
return false;
|
|
25
|
+
if (prevPhoto.src !== nextPhoto.src)
|
|
26
|
+
return false;
|
|
27
|
+
// Compare other relevant props
|
|
28
|
+
if (prevProps.isSelectedMode !== nextProps.isSelectedMode)
|
|
29
|
+
return false;
|
|
30
|
+
if (prevProps.isHiddenGallery !== nextProps.isHiddenGallery)
|
|
31
|
+
return false;
|
|
32
|
+
if (prevProps.index !== nextProps.index)
|
|
33
|
+
return false;
|
|
34
|
+
if (prevProps.isSelected !== nextProps.isSelected)
|
|
35
|
+
return false;
|
|
36
|
+
// If all critical properties are the same, don't re-render
|
|
37
|
+
return true;
|
|
7
38
|
};
|
|
39
|
+
// Memoized component with custom comparison
|
|
40
|
+
const MemoizedImageItem = memo(ImageItemComponents, imageItemPropsAreEqual);
|
|
41
|
+
// Custom comparison function for AlbumImageGalleryInfinite
|
|
42
|
+
const albumGalleryInfinitePropsAreEqual = (prevProps, nextProps) => {
|
|
43
|
+
// Compare simple props first
|
|
44
|
+
if (prevProps.isSelectedMode !== nextProps.isSelectedMode)
|
|
45
|
+
return false;
|
|
46
|
+
if (prevProps.isHiddenGallery !== nextProps.isHiddenGallery)
|
|
47
|
+
return false;
|
|
48
|
+
if (prevProps.isLoading !== nextProps.isLoading)
|
|
49
|
+
return false;
|
|
50
|
+
if (prevProps.isLoadingMore !== nextProps.isLoadingMore)
|
|
51
|
+
return false;
|
|
52
|
+
if (prevProps.hasMore !== nextProps.hasMore)
|
|
53
|
+
return false;
|
|
54
|
+
// Compare imageCollection array deeply
|
|
55
|
+
const prevCollection = prevProps.imageCollection;
|
|
56
|
+
const nextCollection = nextProps.imageCollection;
|
|
57
|
+
// Allow incremental updates - if next has more items, only check if existing items changed
|
|
58
|
+
const minLength = Math.min(prevCollection.length, nextCollection.length);
|
|
59
|
+
// If next collection is smaller, something was removed - need re-render
|
|
60
|
+
if (nextCollection.length < prevCollection.length)
|
|
61
|
+
return false;
|
|
62
|
+
// Check if existing items (at same positions) have changed
|
|
63
|
+
for (let i = 0; i < minLength; i++) {
|
|
64
|
+
const prev = prevCollection[i];
|
|
65
|
+
const next = nextCollection[i];
|
|
66
|
+
if (prev.key !== next.key)
|
|
67
|
+
return false;
|
|
68
|
+
if (prev.src !== next.src)
|
|
69
|
+
return false;
|
|
70
|
+
if (prev.isSelected !== next.isSelected)
|
|
71
|
+
return false;
|
|
72
|
+
if (prev.original !== next.original)
|
|
73
|
+
return false;
|
|
74
|
+
if (JSON.stringify(prev.adjustments) !== JSON.stringify(next.adjustments))
|
|
75
|
+
return false;
|
|
76
|
+
if (prev.frame !== next.frame)
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
// If we reach here, existing items are the same
|
|
80
|
+
// If lengths are equal, no changes - return true
|
|
81
|
+
// If next is longer, new items added - return true (let InfiniteGrid handle new items)
|
|
82
|
+
return true;
|
|
83
|
+
};
|
|
84
|
+
const AlbumImageGalleryInfinite = (props) => {
|
|
85
|
+
const { imageCollection, isSelectedMode, isHiddenGallery, onPreview,
|
|
86
|
+
// isLoading = false,
|
|
87
|
+
isLoadingMore = false, hasMore = false, onSelectedMode = () => { }, onToggleSelect, onLoadMore, } = props;
|
|
88
|
+
// const theme = useTheme();
|
|
89
|
+
const colors = useColors();
|
|
90
|
+
const scrollContainerRef = useRef(null);
|
|
91
|
+
const loadingTriggerRef = useRef(false);
|
|
92
|
+
// Responsive column calculation based on breakpoints (matching original)
|
|
93
|
+
const isMobile = useMediaQuery("(max-width: 750px)");
|
|
94
|
+
// const isTablet = useMediaQuery("(max-width: 900px)");
|
|
95
|
+
const columnWidth = useMemo(() => {
|
|
96
|
+
// if (isMobile) return "100%"; // 1 column on mobile
|
|
97
|
+
if (isMobile)
|
|
98
|
+
return "calc(50% - 0px)"; // 2 columns on tablet
|
|
99
|
+
return "calc(25% - 0px)"; // 4 columns on desktop
|
|
100
|
+
}, [isMobile, isMobile]);
|
|
101
|
+
// Memoize callback functions to prevent unnecessary re-renders
|
|
102
|
+
const handlePreview = useCallback((photo) => () => {
|
|
103
|
+
if (onPreview) {
|
|
104
|
+
onPreview(photo)();
|
|
105
|
+
}
|
|
106
|
+
}, [onPreview]);
|
|
107
|
+
const handleToggleSelect = useCallback((photo) => () => {
|
|
108
|
+
if (onToggleSelect) {
|
|
109
|
+
onToggleSelect(photo)();
|
|
110
|
+
}
|
|
111
|
+
}, [onToggleSelect]);
|
|
112
|
+
const handleScroll = useCallback(async (event) => {
|
|
113
|
+
if (!onLoadMore || !hasMore || isLoadingMore || loadingTriggerRef.current) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const { scrollTop, scrollHeight, clientHeight } = event.currentTarget;
|
|
117
|
+
const scrollPercent = (scrollTop + clientHeight) / scrollHeight;
|
|
118
|
+
// Trigger load more when user scrolls to 80% of the content
|
|
119
|
+
if (scrollPercent > 0.8) {
|
|
120
|
+
loadingTriggerRef.current = true;
|
|
121
|
+
try {
|
|
122
|
+
console.log('[AlbumImageGalleryInfinite] Loading more images...');
|
|
123
|
+
await onLoadMore();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error('[AlbumImageGalleryInfinite] Error loading more images:', error);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
// Reset the trigger after a short delay to prevent rapid firing
|
|
130
|
+
setTimeout(() => {
|
|
131
|
+
loadingTriggerRef.current = false;
|
|
132
|
+
}, 1000);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}, [onLoadMore, hasMore, isLoadingMore]);
|
|
136
|
+
// Reset loading trigger when loading state changes
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
if (!isLoadingMore) {
|
|
139
|
+
loadingTriggerRef.current = false;
|
|
140
|
+
}
|
|
141
|
+
}, [isLoadingMore]);
|
|
142
|
+
return (_jsxs(Box, { ref: scrollContainerRef, onScroll: handleScroll, sx: {
|
|
143
|
+
width: '100%',
|
|
144
|
+
height: '100%',
|
|
145
|
+
overflowY: 'auto',
|
|
146
|
+
overflowX: 'hidden',
|
|
147
|
+
// Hide scrollbar
|
|
148
|
+
scrollbarWidth: 'none', // Firefox
|
|
149
|
+
msOverflowStyle: 'none', // IE/Edge
|
|
150
|
+
'&::-webkit-scrollbar': {
|
|
151
|
+
display: 'none'
|
|
152
|
+
}
|
|
153
|
+
}, children: [_jsx(MasonryInfiniteGrid, { className: "album-masonry-grid", gap: 0, useRecycle: false, threshold: 200, defaultDirection: "end", useFirstRender: true, container: true, containerTag: "div", column: isMobile ? 2 : 4, columnSize: 0, columnSizeRatio: 0,
|
|
154
|
+
// Animation and transition settings to reduce blinking
|
|
155
|
+
transitionDuration: 0, easing: "linear", isEqualSize: false, isConstantSize: false,
|
|
156
|
+
// Prevent layout shifts during updates
|
|
157
|
+
observeChildren: false, renderOnPropertyChange: false, style: {
|
|
158
|
+
// Disable CSS transitions that might cause blinking
|
|
159
|
+
transition: 'none',
|
|
160
|
+
// Improve rendering performance
|
|
161
|
+
willChange: 'auto',
|
|
162
|
+
// Prevent layout shifts
|
|
163
|
+
minHeight: 'auto',
|
|
164
|
+
// width: '100%',
|
|
165
|
+
minWidth: '100%',
|
|
166
|
+
overflow: 'hidden',
|
|
167
|
+
// overflowY: 'scroll', // Enable scrolling
|
|
168
|
+
scrollbarWidth: 'none', // Firefox
|
|
169
|
+
msOverflowStyle: 'none', // IE/Edge
|
|
170
|
+
'&::-webkit-scrollbar': {
|
|
171
|
+
display: 'none'
|
|
172
|
+
}
|
|
173
|
+
}, children: imageCollection.map((photo, index) => (_jsx(Box, { sx: {
|
|
174
|
+
width: columnWidth,
|
|
175
|
+
padding: "4px",
|
|
176
|
+
// Disable transitions to prevent blinking
|
|
177
|
+
transition: 'none !important',
|
|
178
|
+
// Ensure stable layout
|
|
179
|
+
// minHeight: 'auto',
|
|
180
|
+
// Improve rendering performance
|
|
181
|
+
willChange: 'auto',
|
|
182
|
+
// Ensure images maintain aspect ratio
|
|
183
|
+
"& img": {
|
|
184
|
+
width: "100%",
|
|
185
|
+
// height: "auto",
|
|
186
|
+
// objectFit: "cover",
|
|
187
|
+
// borderRadius: "8px",
|
|
188
|
+
// Disable image transitions
|
|
189
|
+
transition: 'none !important',
|
|
190
|
+
// Prevent layout shifts during loading
|
|
191
|
+
display: 'block'
|
|
192
|
+
}
|
|
193
|
+
}, children: _jsx(MemoizedImageItem, { margin: "0px", index: index, photo: photo, data: photo, direction: "column", isFullScreenMode: false, isSelected: photo.isSelected ?? false, isSelectedMode: isSelectedMode, isHiddenGallery: isHiddenGallery, onPreview: handlePreview(photo), onSelectedMode: onSelectedMode, onToggleSelect: handleToggleSelect(photo) }) }, photo.key + photo.adjustments?.toString()))) }), isLoadingMore && (_jsx(Box, { sx: {
|
|
194
|
+
display: 'flex',
|
|
195
|
+
justifyContent: 'center',
|
|
196
|
+
alignItems: 'center',
|
|
197
|
+
padding: 2,
|
|
198
|
+
width: '100%'
|
|
199
|
+
}, children: _jsx(CircularProgress, { size: 24, sx: { color: colors.onSurfaceVariant } }) })), !hasMore && imageCollection.length > 0 && (_jsx(Box, { sx: {
|
|
200
|
+
display: 'flex',
|
|
201
|
+
justifyContent: 'center',
|
|
202
|
+
alignItems: 'center',
|
|
203
|
+
padding: 2,
|
|
204
|
+
width: '100%',
|
|
205
|
+
color: colors.onSurfaceVariant,
|
|
206
|
+
fontSize: '0.875rem'
|
|
207
|
+
}, children: "No more images to load" }))] }));
|
|
208
|
+
};
|
|
209
|
+
export default AlbumImageGalleryInfinite;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { GallerySetup } from "../../../services/type";
|
|
2
|
+
interface PhotoProps<T> {
|
|
3
|
+
src: string;
|
|
4
|
+
alt: string;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
key: string;
|
|
8
|
+
}
|
|
9
|
+
interface Props {
|
|
10
|
+
margin?: any;
|
|
11
|
+
index: number;
|
|
12
|
+
photo: PhotoProps<GallerySetup>;
|
|
13
|
+
data: GallerySetup;
|
|
14
|
+
direction: "row" | "column";
|
|
15
|
+
isSelectedMode: boolean | undefined;
|
|
16
|
+
isFullScreenMode: boolean;
|
|
17
|
+
isSelected: boolean;
|
|
18
|
+
isHiddenGallery: boolean | undefined;
|
|
19
|
+
onToggleSelect: () => void;
|
|
20
|
+
onPreview: () => void;
|
|
21
|
+
onSelectedMode: () => void | undefined;
|
|
22
|
+
enableEditor?: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare const ImageItemComponents: (props: Props) => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export default ImageItemComponents;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { Box, CardMedia, useTheme } from "@mui/material";
|
|
4
|
+
import { TickCircle } from "iconsax-react";
|
|
5
|
+
import useColors from '../../../themes/colors';
|
|
6
|
+
import CustomTickIcon from "./svg/Tick";
|
|
7
|
+
import { useImageProcessor } from "../../../lib/hooks/useImageProcessor";
|
|
8
|
+
import { neutral } from "./colorsGallery";
|
|
9
|
+
import { log } from "../../../utils/logger";
|
|
10
|
+
const imgStyle = {
|
|
11
|
+
transition: "transform .135s cubic-bezier(0.0,0.0,0.2,1),opacity linear .15s",
|
|
12
|
+
width: "100%",
|
|
13
|
+
// objectFit: "contain",
|
|
14
|
+
//height: "100%",
|
|
15
|
+
};
|
|
16
|
+
const selectedImgStyle = {
|
|
17
|
+
borderRadius: "8px",
|
|
18
|
+
transform: "translateZ(0px) scale3d(1, 1, 1)",
|
|
19
|
+
// transition: "transform .135s cubic-bezier(0.0,0.0,0.2,1),opacity linear .15s"
|
|
20
|
+
};
|
|
21
|
+
const ImageItemComponents = (props) => {
|
|
22
|
+
const { photo, margin, enableEditor = true, data } = props;
|
|
23
|
+
const theme = useTheme();
|
|
24
|
+
const imageData = data;
|
|
25
|
+
const colors = useColors();
|
|
26
|
+
// Memoize adjustments to prevent infinite re-renders
|
|
27
|
+
// Use the image processor hook
|
|
28
|
+
const { processedImageSrc, isProcessingComplete } = useImageProcessor({
|
|
29
|
+
photoId: photo.key,
|
|
30
|
+
photoSrc: photo.src,
|
|
31
|
+
enableEditor,
|
|
32
|
+
adjustments: imageData?.adjustments,
|
|
33
|
+
frame: imageData?.frame || null,
|
|
34
|
+
});
|
|
35
|
+
const styleHiddenGallery = useMemo(() => {
|
|
36
|
+
if (props.isHiddenGallery) {
|
|
37
|
+
return { filter: "blur(20px)", pointerEvents: "none" };
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
}, [props.isHiddenGallery]);
|
|
43
|
+
const commonStyle = useMemo(() => {
|
|
44
|
+
return {
|
|
45
|
+
backgroundColor: neutral.white,
|
|
46
|
+
overflow: "hidden",
|
|
47
|
+
position: "relative",
|
|
48
|
+
width: "100%",
|
|
49
|
+
aspectRatio: `${photo.width}/${photo.height}`,
|
|
50
|
+
};
|
|
51
|
+
}, [props.direction, props.photo]);
|
|
52
|
+
const handleImageClick = () => {
|
|
53
|
+
log.debug({
|
|
54
|
+
isFullMode: props.isFullScreenMode,
|
|
55
|
+
isShowGallery: props.isHiddenGallery,
|
|
56
|
+
isSelectedMode: props.isSelectedMode,
|
|
57
|
+
isSelected: props.isSelected,
|
|
58
|
+
}, "handleImageClick");
|
|
59
|
+
if (!props.isSelectedMode && !props.isSelected) {
|
|
60
|
+
props.onSelectedMode();
|
|
61
|
+
}
|
|
62
|
+
if (!props.isFullScreenMode && !props.isHiddenGallery) {
|
|
63
|
+
if (props.isSelectedMode || props.isSelected) {
|
|
64
|
+
// If we're in selection mode OR this image is already selected,
|
|
65
|
+
// clicking toggles the selection
|
|
66
|
+
log.debug("handleImageClick with toggle select");
|
|
67
|
+
props.onToggleSelect();
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Not in selection mode and image not selected
|
|
71
|
+
// Enter selection mode and select this image in one action
|
|
72
|
+
log.debug("handleImageClick entering selection mode and selecting image");
|
|
73
|
+
if (props.onSelectedMode) {
|
|
74
|
+
props.onSelectedMode(); // This should trigger selection mode globally
|
|
75
|
+
}
|
|
76
|
+
props.onToggleSelect(); // Select this specific image
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const handleImageSelectedIconClick = () => {
|
|
81
|
+
log.debug("handleImageSelectedIconClick");
|
|
82
|
+
if (!props.isFullScreenMode) {
|
|
83
|
+
if (!props.isSelectedMode) {
|
|
84
|
+
props.onSelectedMode();
|
|
85
|
+
}
|
|
86
|
+
props.onToggleSelect();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const imageSx = useMemo(() => {
|
|
90
|
+
const baseStyles = props.isSelected ? {
|
|
91
|
+
...imgStyle,
|
|
92
|
+
...selectedImgStyle,
|
|
93
|
+
...styleHiddenGallery,
|
|
94
|
+
aspectRatio: `${photo.width}/${photo.height}`,
|
|
95
|
+
} : {
|
|
96
|
+
...imgStyle,
|
|
97
|
+
...styleHiddenGallery,
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
...baseStyles,
|
|
101
|
+
// Show loading state only on first load, then keep images visible during transitions
|
|
102
|
+
opacity: (!processedImageSrc || !isProcessingComplete) && processedImageSrc === '' ? 0 : 1,
|
|
103
|
+
transition: 'opacity 0.15s ease-in-out',
|
|
104
|
+
};
|
|
105
|
+
}, [props.isSelected, styleHiddenGallery, photo.width, photo.height, processedImageSrc, isProcessingComplete]);
|
|
106
|
+
const boxNotSelected = useMemo(() => ({
|
|
107
|
+
margin,
|
|
108
|
+
// height: photo.height,
|
|
109
|
+
...commonStyle,
|
|
110
|
+
transition: ".3s",
|
|
111
|
+
// "&:hover": { padding: "12px", backgroundColor: "primary.light1" },
|
|
112
|
+
"&:-webkit-transition": { transition: ".3s" },
|
|
113
|
+
"&:hover > .checkbox": { display: props.isHiddenGallery ? "" : "block" },
|
|
114
|
+
cursor: props.isFullScreenMode || props.isHiddenGallery ? "inherit" : "pointer",
|
|
115
|
+
backgroundColor: props.isFullScreenMode
|
|
116
|
+
? "rgba(0,0,0,0.1)"
|
|
117
|
+
: "transparent",
|
|
118
|
+
}), [margin, commonStyle, props.isHiddenGallery, props.isFullScreenMode]);
|
|
119
|
+
const boxSelected = useMemo(() => ({
|
|
120
|
+
margin,
|
|
121
|
+
// height: photo.height,
|
|
122
|
+
...commonStyle,
|
|
123
|
+
cursor: props.isFullScreenMode || props.isHiddenGallery ? "inherit" : "pointer",
|
|
124
|
+
transition: ".3s",
|
|
125
|
+
"&:-webkit-transition": { transition: ".3s" },
|
|
126
|
+
padding: { xs: "13px 12px", sm: "21.31px 25.56px 21.32px 27.68px" },
|
|
127
|
+
backgroundColor: colors.onSurface,
|
|
128
|
+
}), [margin, commonStyle, theme.palette.light, props.isFullScreenMode, props.isHiddenGallery,]);
|
|
129
|
+
const boxOuterSx = useMemo(() => {
|
|
130
|
+
if (props.isFullScreenMode) {
|
|
131
|
+
return {
|
|
132
|
+
margin,
|
|
133
|
+
...commonStyle,
|
|
134
|
+
//width: props.data.width,
|
|
135
|
+
//height: props.data.height,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (props.isSelected) {
|
|
140
|
+
return { ...boxSelected };
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
return { ...boxNotSelected };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}, [
|
|
147
|
+
props.isFullScreenMode,
|
|
148
|
+
photo.height,
|
|
149
|
+
photo.width,
|
|
150
|
+
commonStyle,
|
|
151
|
+
boxSelected,
|
|
152
|
+
boxNotSelected,
|
|
153
|
+
margin,
|
|
154
|
+
props.isSelected,
|
|
155
|
+
]);
|
|
156
|
+
return (_jsxs(Box, { id: "Box_image", sx: boxOuterSx, className: "image", children: [!props.isHiddenGallery &&
|
|
157
|
+
(props.isSelected ? (_jsx(Box, { color: colors.onSurface, onClick: handleImageSelectedIconClick, sx: {
|
|
158
|
+
position: "absolute",
|
|
159
|
+
width: "19px",
|
|
160
|
+
height: "19px",
|
|
161
|
+
zIndex: "2",
|
|
162
|
+
left: "5px",
|
|
163
|
+
top: "5px",
|
|
164
|
+
borderRadius: { xs: "50%", sm: 0 },
|
|
165
|
+
}, className: "checkbox", children: _jsx(CustomTickIcon, {}) })) : (_jsx(Box, { color: "neutral.light2", onClick: handleImageSelectedIconClick, sx: {
|
|
166
|
+
position: "absolute",
|
|
167
|
+
width: "19px",
|
|
168
|
+
height: "19px",
|
|
169
|
+
zIndex: "1",
|
|
170
|
+
left: "5px",
|
|
171
|
+
top: "5px",
|
|
172
|
+
display: props.isSelectedMode ? "block" : "none",
|
|
173
|
+
visibility: {
|
|
174
|
+
xs: props.isSelectedMode ? "visible" : "hidden",
|
|
175
|
+
sm: "visible",
|
|
176
|
+
},
|
|
177
|
+
}, className: "checkbox", children: _jsx(TickCircle, { style: { width: "24px", height: "24px", fill: "black" }, color: "white" }) }))), _jsx(CardMedia, { id: "card_media", component: "img", className: "image", loading: "lazy", alt: photo.alt, sx: imageSx, src: processedImageSrc, width: "100%", onClick: handleImageClick })] }, photo.key));
|
|
178
|
+
};
|
|
179
|
+
export default ImageItemComponents;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { SvgIcon } from "@mui/material";
|
|
3
|
+
const Tick = () => {
|
|
4
|
+
return (_jsx(SvgIcon, { style: { width: "29px", height: "29px" }, children: _jsxs("svg", { width: "36", height: "36", viewBox: "0 0 36 36", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("rect", { x: "5", y: "5", width: "22", height: "22", rx: "11", fill: "white" }), _jsx("path", { d: "M20 13L14.5 18.5L12 16", stroke: "black", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }) }));
|
|
5
|
+
};
|
|
6
|
+
export default Tick;
|
|
@@ -4,7 +4,6 @@ import useHonchoTypography from "../../themes/honchoTheme";
|
|
|
4
4
|
import useColors from "../../themes/colors";
|
|
5
5
|
import HBulkAccordionColorAdjustmentColors from "./HBulkAccordionColorAdjustmentColors";
|
|
6
6
|
import HBulkAccordionColorAdjustmentLight from "./HBulkAccordionColorAdjustmentLight";
|
|
7
|
-
import HBulkAccordionColorAdjustmentDetails from "./HBulkAccordionColorAdjustmentDetails";
|
|
8
7
|
export default function HBulkAccordionColorAdjustment(props) {
|
|
9
8
|
const typography = useHonchoTypography();
|
|
10
9
|
const colors = useColors();
|
|
@@ -27,5 +26,5 @@ export default function HBulkAccordionColorAdjustment(props) {
|
|
|
27
26
|
}
|
|
28
27
|
};
|
|
29
28
|
const isPanelExpanded = (panelName) => props.expandedPanels.includes(panelName);
|
|
30
|
-
return (_jsx(_Fragment, { children: _jsxs(Stack, { direction: "column", sx: { accordionStyle }, children: [_jsxs(Accordion, { sx: accordionStyle, expanded: isPanelExpanded('whiteBalance'), onChange: props.onPanelChange('whiteBalance'), 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 }, children: "Color" }), _jsx(CardMedia, { component: "img", image: isPanelExpanded('whiteBalance') ? "/v1/svg/expanded-editor.svg" : "/v1/svg/expand-editor.svg", sx: { width: "11.67px", height: "5.83px" } })] }) }), _jsx(AccordionDetails, { sx: { pr: "
|
|
29
|
+
return (_jsx(_Fragment, { children: _jsxs(Stack, { direction: "column", sx: { accordionStyle }, children: [_jsxs(Accordion, { sx: accordionStyle, expanded: isPanelExpanded('whiteBalance'), onChange: props.onPanelChange('whiteBalance'), disableGutters: true, children: [_jsx(AccordionSummary, { sx: { pr: 0 }, children: _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { width: '100%', pr: "16px" }, children: [_jsx(Typography, { sx: { ...typography.titleMedium }, children: "Color" }), _jsx(CardMedia, { component: "img", image: isPanelExpanded('whiteBalance') ? "/v1/svg/expanded-editor.svg" : "/v1/svg/expand-editor.svg", sx: { width: "11.67px", height: "5.83px" } })] }) }), _jsx(AccordionDetails, { sx: { pr: "2px" }, children: _jsx(HBulkAccordionColorAdjustmentColors, { onTempDecreaseMax: props.onTempDecreaseMax, onTempDecrease: props.onTempDecrease, onTempIncrease: props.onTempIncrease, onTempIncreaseMax: props.onTempIncreaseMax, onTintDecreaseMax: props.onTintDecreaseMax, onTintDecrease: props.onTintDecrease, onTintIncrease: props.onTintIncrease, onTintIncreaseMax: props.onTintIncreaseMax, onVibranceDecreaseMax: props.onVibranceDecreaseMax, onVibranceDecrease: props.onVibranceDecrease, onVibranceIncrease: props.onVibranceIncrease, onVibranceIncreaseMax: props.onVibranceIncreaseMax, onSaturationDecreaseMax: props.onSaturationDecreaseMax, onSaturationDecrease: props.onSaturationDecrease, onSaturationIncrease: props.onSaturationIncrease, onSaturationIncreaseMax: props.onSaturationIncreaseMax }) })] }), _jsxs(Accordion, { sx: accordionStyle, expanded: isPanelExpanded('light'), onChange: props.onPanelChange('light'), disableGutters: true, children: [_jsx(AccordionSummary, { sx: { pr: 0 }, children: _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { width: '100%', pr: "16px" }, children: [_jsx(Typography, { sx: { ...typography.titleMedium }, children: "Light" }), _jsx(CardMedia, { component: "img", image: isPanelExpanded('light') ? "/v1/svg/expanded-editor.svg" : "/v1/svg/expand-editor.svg", sx: { width: "11.67px", height: "5.83px" } })] }) }), _jsx(AccordionDetails, { sx: { pr: "2px" }, children: _jsx(HBulkAccordionColorAdjustmentLight, { onExposureDecreaseMax: props.onExposureDecreaseMax, onExposureDecrease: props.onExposureDecrease, onExposureIncrease: props.onExposureIncrease, onExposureIncreaseMax: props.onExposureIncreaseMax, onContrastDecreaseMax: props.onContrastDecreaseMax, onContrastDecrease: props.onContrastDecrease, onContrastIncrease: props.onContrastIncrease, onContrastIncreaseMax: props.onContrastIncreaseMax, onHighlightsDecreaseMax: props.onHighlightsDecreaseMax, onHighlightsDecrease: props.onHighlightsDecrease, onHighlightsIncrease: props.onHighlightsIncrease, onHighlightsIncreaseMax: props.onHighlightsIncreaseMax, onShadowsDecreaseMax: props.onShadowsDecreaseMax, onShadowsDecrease: props.onShadowsDecrease, onShadowsIncrease: props.onShadowsIncrease, onShadowsIncreaseMax: props.onShadowsIncreaseMax, onWhitesDecreaseMax: props.onWhitesDecreaseMax, onWhitesDecrease: props.onWhitesDecrease, onWhitesIncrease: props.onWhitesIncrease, onWhitesIncreaseMax: props.onWhitesIncreaseMax, onBlacksDecreaseMax: props.onBlacksDecreaseMax, onBlacksDecrease: props.onBlacksDecrease, onBlacksIncrease: props.onBlacksIncrease, onBlacksIncreaseMax: props.onBlacksIncreaseMax }) })] })] }) }));
|
|
31
30
|
}
|
|
@@ -89,7 +89,7 @@ export default function HBulkAccordionColorAdjustmentColors(props) {
|
|
|
89
89
|
mr: "12px",
|
|
90
90
|
border: "1px solid white",
|
|
91
91
|
borderRadius: "100px",
|
|
92
|
-
}, children: _jsx(CardMedia, { component: "img", image: "/v1/svg/bulk-editor-max-button-right.svg", sx: { ml: "2px" } }) })] }), _jsx(Stack, { direction: "row", justifyContent: "space-between", sx: { pb: "8px", pt: "16px" }, children: _jsx(Typography, { sx: { ...typography.bodyMedium }, children: "Saturation" }) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", sx: { p: "0px", m: "0px", pt: "2px", pb: "
|
|
92
|
+
}, children: _jsx(CardMedia, { component: "img", image: "/v1/svg/bulk-editor-max-button-right.svg", sx: { ml: "2px" } }) })] }), _jsx(Stack, { direction: "row", justifyContent: "space-between", sx: { pb: "8px", pt: "16px" }, children: _jsx(Typography, { sx: { ...typography.bodyMedium }, children: "Saturation" }) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", sx: { p: "0px", m: "0px", pt: "2px", pb: "16px" }, children: [_jsx(IconButton, { onClick: props.onSaturationDecreaseMax, sx: {
|
|
93
93
|
width: "38.5px",
|
|
94
94
|
height: "26px",
|
|
95
95
|
py: "2px",
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { SelectChangeEvent } from "@mui/material";
|
|
3
2
|
type Preset = {
|
|
4
3
|
id: string;
|
|
5
4
|
name: string;
|
|
@@ -10,14 +9,11 @@ interface Props {
|
|
|
10
9
|
expandedPanels: string[];
|
|
11
10
|
presetMenuAnchorEl: null | HTMLElement;
|
|
12
11
|
activePresetMenuId: string | null;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
onSelectPreset: (
|
|
12
|
+
isPresetCreatedSet?: boolean;
|
|
13
|
+
onChange: (panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => void;
|
|
14
|
+
onSelectPreset: (id: string) => void;
|
|
16
15
|
onPresetMenuClick: (event: React.MouseEvent<HTMLElement>, presetId: string) => void;
|
|
17
16
|
onPresetMenuClose: () => void;
|
|
18
|
-
onRemovePreset: () => void;
|
|
19
|
-
onRenamePreset: () => void;
|
|
20
|
-
onDeletePreset: () => void;
|
|
21
17
|
onOpenPresetModal: () => void;
|
|
22
18
|
}
|
|
23
19
|
export default function HBulkPreset(props: Props): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from "react";
|
|
2
3
|
import { Box, MenuItem, FormControl, Select, Stack, Accordion, AccordionSummary, AccordionDetails, CardMedia, Typography, IconButton, Button } from "@mui/material";
|
|
3
4
|
import useHonchoTypography from "../../themes/honchoTheme";
|
|
4
5
|
import useColors from "../../themes/colors";
|
|
5
|
-
// Static `presets` array has been removed.
|
|
6
6
|
export default function HBulkPreset(props) {
|
|
7
7
|
const typography = useHonchoTypography();
|
|
8
8
|
const colors = useColors();
|
|
9
|
-
const isMenuOpen = Boolean(props.presetMenuAnchorEl);
|
|
10
9
|
const isPanelExpanded = (panelName) => props.expandedPanels.includes(panelName);
|
|
11
10
|
const accordionStyle = {
|
|
12
11
|
backgroundColor: colors.onBackground,
|
|
@@ -18,26 +17,26 @@ export default function HBulkPreset(props) {
|
|
|
18
17
|
};
|
|
19
18
|
const CustomSelectIcon = (iconProps) => {
|
|
20
19
|
const isExpanded = iconProps.className?.includes('MuiSelect-iconOpen');
|
|
21
|
-
return (_jsx(CardMedia, { component: "img", image: isExpanded ? "/v1/svg/
|
|
20
|
+
return (_jsx(CardMedia, { component: "img", image: isExpanded ? "/v1/svg/expanded-editor.svg" : "/v1/svg/expand-editor.svg", sx: { width: "11.67px", height: "5.83px", right: '14px', position: 'absolute', pointerEvents: 'none' } }));
|
|
22
21
|
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
const handleSelectChange = (event) => {
|
|
23
|
+
props.onSelectPreset(event.target.value);
|
|
24
|
+
};
|
|
25
|
+
const renderValue = useCallback((selectedId) => {
|
|
26
|
+
if (selectedId === 'MULTIPLE_PRESETS') {
|
|
27
|
+
return _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, children: "Multiple presets" });
|
|
28
|
+
}
|
|
29
|
+
if (selectedId === 'NO_SELECTION' || !selectedId || selectedId === '') {
|
|
30
|
+
return _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, children: "Select" });
|
|
31
|
+
}
|
|
32
|
+
const selectedPresetObject = props.presets.find(p => p.id === selectedId);
|
|
33
|
+
if (!selectedPresetObject) {
|
|
34
|
+
return _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, children: "Select" });
|
|
35
|
+
}
|
|
36
|
+
return _jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, children: selectedPresetObject.name });
|
|
37
|
+
}, [props.presets, typography.bodyMedium, colors.surface]);
|
|
38
|
+
// The useEffect that forced re-renders has been removed.
|
|
39
|
+
return (_jsx(_Fragment, { children: _jsx(Stack, { children: _jsxs(Accordion, { sx: accordionStyle, expanded: isPanelExpanded('preset'), onChange: props.onChange('preset'), disableGutters: true, children: [_jsx(AccordionSummary, { sx: { pr: 0 }, children: _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { width: '100%', pr: "16px" }, 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: { pl: "16px" }, children: _jsx(FormControl, { fullWidth: true, children: _jsxs(Select, { fullWidth: true, value: props.selectedPreset, onChange: handleSelectChange, IconComponent: CustomSelectIcon, renderValue: renderValue, MenuProps: {
|
|
35
40
|
slotProps: { paper: { sx: { backgroundColor: colors.onBackground, color: colors.surface, border: `1px solid ${colors.onSurfaceVariant1}`, mt: '20px', width: '178px', boxShadow: 'none' } } }
|
|
36
|
-
}, sx: { border: `1px solid ${colors.outlineVariant}`, height: '44px', width: '
|
|
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" }) })] }) }) })] }) }) }));
|
|
41
|
+
}, sx: { border: `1px solid ${colors.outlineVariant}`, height: '44px', width: '202px', 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, disabled: props.isPresetCreatedSet, children: "Create Preset" }) })] }) }) })] }) }) }));
|
|
43
42
|
}
|
|
@@ -8,8 +8,8 @@ interface Props {
|
|
|
8
8
|
presets: Preset[];
|
|
9
9
|
selectedPresetBulk: string;
|
|
10
10
|
onOpenPresetModalBulk: () => void;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
onSelectPreset: (event: SelectChangeEvent<string>) => void;
|
|
12
|
+
onPresetMenuClick: (event: React.MouseEvent<HTMLElement>, presetId: string) => void;
|
|
13
13
|
}
|
|
14
14
|
export default function HBulkPresetMobile(props: Props): import("react/jsx-runtime").JSX.Element;
|
|
15
15
|
export {};
|