@yogiswara/honcho-editor-ui 2.2.5 → 2.2.7

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.
@@ -1,16 +1,8 @@
1
1
  import React from "react";
2
- import { AdjustmentValues } from "../../../lib/editor/honcho-editor";
3
- import type { PhotoData as BulkPhotoData } from "../../../hooks/editor/useHonchoEditorBulk";
4
- export interface ExtendedPhotoData extends BulkPhotoData {
5
- adjustments?: Partial<AdjustmentValues>;
6
- frame?: string;
7
- }
2
+ import type { PhotoData } from "../../../hooks/editor/useHonchoEditorBulk";
8
3
  interface ImageGalleryProps {
9
- imageCollection: ExtendedPhotoData[];
10
- isSelectedMode: boolean;
11
- isHiddenGallery: boolean;
12
- enableEditor: boolean;
13
- onToggleSelect: (photo: ExtendedPhotoData) => void;
4
+ imageCollection: PhotoData[];
5
+ onToggleSelect: (photo: PhotoData) => void;
14
6
  }
15
7
  export declare const AlbumImageGallery: React.FC<ImageGalleryProps>;
16
8
  export {};
@@ -4,9 +4,7 @@ import { Box, Stack } from "@mui/material";
4
4
  import Masonry, { ResponsiveMasonry } from "react-responsive-masonry";
5
5
  import GalleryImageItem from "./ImageItem";
6
6
  export const AlbumImageGallery = (props) => {
7
- const { imageCollection, isSelectedMode, isHiddenGallery, enableEditor, // Destructure the new prop
8
- onToggleSelect, } = props;
9
- console.log("imageCollection: ", imageCollection);
7
+ const { imageCollection, onToggleSelect } = props;
10
8
  return (_jsx(Stack, { sx: { width: '100%', maxHeight: '100%', overflowY: 'auto' }, children: _jsx(ResponsiveMasonry, { columnsCountBreakPoints: { 750: 2, 900: 4 }, children: _jsx(Masonry, { children: imageCollection.map((photo, index) => {
11
9
  // This guard clause is still important for runtime safety.
12
10
  if (!photo.key || !photo.src) {
@@ -25,8 +23,6 @@ export const AlbumImageGallery = (props) => {
25
23
  // in case ImageItem needs it for other operations.
26
24
  photo: photo,
27
25
  };
28
- return (_jsx(Box, { sx: { m: 0.5 }, children: _jsx(GalleryImageItem, { margin: "0px", index: index,
29
- // UPDATED: Pass the new, correctly-typed object.
30
- photo: imageItemPhotoProps, direction: "column", isFullScreenMode: false, isSelected: photo.isSelected, isSelectedMode: isSelectedMode, isHiddenGallery: isHiddenGallery, onToggleSelect: () => { onToggleSelect(photo); }, enableEditor: enableEditor, adjustments: photo.adjustments, frame: photo.frame, data: photo }) }, photo.key));
26
+ return (_jsx(Box, { sx: { m: 0.5 }, children: _jsx(GalleryImageItem, { margin: "0px", index: index, direction: "column", onToggleSelect: () => { onToggleSelect(photo); }, data: photo }) }, photo.key));
31
27
  }) }) }) }));
32
28
  };
@@ -1,26 +1,10 @@
1
- import type { AdjustmentValues } from "../../../lib/editor/honcho-editor";
2
- import { GallerySetup } from "../../../hooks/editor/type";
3
- interface PhotoProps<T> {
4
- src: string;
5
- alt?: string;
6
- width: number;
7
- height: number;
8
- key: string;
9
- }
1
+ import { PhotoData } from "../../../hooks/editor/useHonchoEditorBulk";
10
2
  interface Props {
11
3
  margin?: any;
12
4
  index: number;
13
- photo: PhotoProps<GallerySetup>;
14
- data: GallerySetup;
5
+ data: PhotoData;
15
6
  direction: "row" | "column";
16
- isSelectedMode: boolean;
17
- isFullScreenMode: boolean;
18
- isSelected?: boolean;
19
- isHiddenGallery: boolean;
20
7
  onToggleSelect: () => void;
21
- enableEditor?: boolean;
22
- adjustments?: Partial<AdjustmentValues>;
23
- frame?: string | null;
24
8
  }
25
9
  declare const GalleryImageItem: (props: Props) => import("react/jsx-runtime").JSX.Element;
26
10
  export default GalleryImageItem;
@@ -1,8 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
3
  import { Box, CardMedia, useTheme } from "@mui/material";
4
- import { TickCircle } from "iconsax-react";
5
- import CustomTickIcon from "../svg/Tick";
6
4
  import { neutral } from "../../../color";
7
5
  const initialAdjustments = {
8
6
  temperature: 0, tint: 0, saturation: 0, vibrance: 0, exposure: 0, contrast: 0,
@@ -20,70 +18,32 @@ const selectedImgStyle = {
20
18
  // transition: "transform .135s cubic-bezier(0.0,0.0,0.2,1),opacity linear .15s"
21
19
  };
22
20
  const GalleryImageItem = (props) => {
23
- const { photo, margin, adjustments, isSelected = false, data } = props;
21
+ const { margin, data } = props;
24
22
  const theme = useTheme();
25
23
  const imageData = data;
26
- const hasAdjustments = useMemo(() => {
27
- if (!adjustments)
28
- return false;
29
- return Object.keys(initialAdjustments).some(key => adjustments[key] !== initialAdjustments[key]);
30
- }, [adjustments]);
31
- const styleHiddenGallery = useMemo(() => {
32
- if (props.isHiddenGallery) {
33
- return { filter: "blur(20px)", pointerEvents: "none" };
34
- }
35
- else {
36
- return {};
37
- }
38
- }, [props.isHiddenGallery]);
39
24
  const commonStyle = useMemo(() => {
40
25
  return {
41
26
  backgroundColor: neutral.white,
42
27
  overflow: "hidden",
43
28
  position: "relative",
44
29
  width: "100%",
45
- aspectRatio: `${photo.width}/${photo.height}`,
30
+ aspectRatio: `${imageData.width}/${imageData.height}`,
46
31
  };
47
- }, [props.direction, props.photo]);
48
- const handleImageClick = () => {
49
- console.debug({
50
- isFullMode: props.isFullScreenMode,
51
- isShowGallery: props.isHiddenGallery,
52
- }, "handleImageClick");
53
- if (!props.isFullScreenMode && !props.isHiddenGallery) {
54
- if (props.isSelectedMode) {
55
- console.debug("handleImageClick with toggle select");
56
- props.onToggleSelect();
57
- }
58
- else {
59
- console.debug("handleImageClick with preview");
60
- }
61
- }
62
- };
63
- const handleImageSelectedIconClick = () => {
64
- console.debug("handleImageSelectedIconClick");
65
- if (!props.isFullScreenMode) {
66
- if (!props.isSelectedMode) {
67
- }
68
- props.onToggleSelect();
69
- }
70
- };
32
+ }, [props.direction, imageData]);
71
33
  const imageSx = useMemo(() => {
72
- const baseStyles = isSelected ? {
34
+ const baseStyles = imageData.isSelected ? {
73
35
  ...imgStyle,
74
36
  ...selectedImgStyle,
75
- ...styleHiddenGallery,
76
- aspectRatio: `${photo.width}/${photo.height}`,
37
+ aspectRatio: `${imageData.width}/${imageData.height}`,
77
38
  } : {
78
39
  ...imgStyle,
79
- ...styleHiddenGallery,
80
40
  };
81
41
  return {
82
42
  ...baseStyles,
83
43
  opacity: 1, // Previously depended on isProcessingComplete
84
44
  transition: 'opacity 0.3s ease-in-out',
85
45
  };
86
- }, [isSelected, styleHiddenGallery, photo.width, photo.height]);
46
+ }, [props.data.isSelected, imageData.width, imageData.height]);
87
47
  const boxNotSelected = useMemo(() => ({
88
48
  margin,
89
49
  // height: photo.height,
@@ -91,17 +51,15 @@ const GalleryImageItem = (props) => {
91
51
  transition: ".3s",
92
52
  // "&:hover": { padding: "12px", backgroundColor: "primary.light1" },
93
53
  "&:-webkit-transition": { transition: ".3s" },
94
- "&:hover > .checkbox": { display: props.isHiddenGallery ? "" : "block" },
95
- cursor: props.isFullScreenMode || props.isHiddenGallery ? "inherit" : "pointer",
96
- backgroundColor: props.isFullScreenMode
97
- ? "rgba(0,0,0,0.1)"
98
- : "transparent",
99
- }), [margin, commonStyle, props.isHiddenGallery, props.isFullScreenMode]);
54
+ "&:hover > .checkbox": { display: "block" },
55
+ cursor: "pointer",
56
+ backgroundColor: "transparent",
57
+ }), [margin, commonStyle]);
100
58
  const boxSelected = useMemo(() => ({
101
59
  margin,
102
60
  // height: photo.height,
103
61
  ...commonStyle,
104
- cursor: props.isFullScreenMode || props.isHiddenGallery ? "inherit" : "pointer",
62
+ cursor: "pointer",
105
63
  transition: ".3s",
106
64
  "&:-webkit-transition": { transition: ".3s" },
107
65
  padding: { xs: "13px 12px", sm: "21.31px 25.56px 21.32px 27.68px" },
@@ -109,55 +67,15 @@ const GalleryImageItem = (props) => {
109
67
  margin,
110
68
  commonStyle,
111
69
  theme.palette.light,
112
- props.isFullScreenMode,
113
- props.isHiddenGallery,
114
70
  ]);
115
71
  const boxOuterSx = useMemo(() => {
116
- if (props.isFullScreenMode) {
117
- return {
118
- margin,
119
- ...commonStyle,
120
- };
72
+ if (props.data.isSelected) {
73
+ return { ...boxSelected };
121
74
  }
122
75
  else {
123
- if (props.isSelected) {
124
- return { ...boxSelected };
125
- }
126
- else {
127
- return { ...boxNotSelected };
128
- }
76
+ return { ...boxNotSelected };
129
77
  }
130
- }, [
131
- props.isFullScreenMode,
132
- photo.height,
133
- photo.width,
134
- commonStyle,
135
- boxSelected,
136
- boxNotSelected,
137
- margin,
138
- props.isSelected,
139
- ]);
140
- return (_jsxs(Box, { id: "Box_image", sx: boxOuterSx, className: "image", children: [!props.isHiddenGallery &&
141
- (hasAdjustments && isSelected ? (_jsx(Box, { color: "primary.dark1", onClick: handleImageSelectedIconClick, sx: {
142
- position: "absolute",
143
- width: "19px",
144
- height: "19px",
145
- zIndex: "2",
146
- left: "5px",
147
- top: "5px",
148
- borderRadius: { xs: "50%", sm: 0 },
149
- }, className: "checkbox", children: _jsx(CustomTickIcon, {}) })) : (_jsx(Box, { color: "neutral.light2", onClick: handleImageSelectedIconClick, sx: {
150
- position: "absolute",
151
- width: "19px",
152
- height: "19px",
153
- zIndex: "1",
154
- left: "5px",
155
- top: "5px",
156
- display: "none",
157
- visibility: {
158
- xs: props.isSelectedMode ? "visible" : "hidden",
159
- sm: "visible",
160
- },
161
- }, className: "checkbox", children: _jsx(TickCircle, { style: { width: "24px", height: "24px" }, color: "white" }) }))), _jsx(CardMedia, { id: "card_media", component: "img", className: "image", loading: "lazy", alt: imageData.alt ?? "Image", sx: imageSx, src: imageData.src, width: "100%", onClick: handleImageClick })] }, photo.key));
78
+ }, [imageData.height, imageData.width, commonStyle, boxSelected, boxNotSelected, margin]);
79
+ return (_jsx(Box, { id: "Box_image", sx: boxOuterSx, className: "image", children: _jsx(CardMedia, { id: "card_media", component: "img", className: "image", loading: "lazy", alt: imageData.alt ?? "Image", sx: imageSx, src: imageData.src, width: "100%", onClick: props.onToggleSelect }) }, imageData.key));
162
80
  };
163
81
  export default GalleryImageItem;
@@ -177,7 +177,7 @@ export declare function useHonchoEditor(controller: Controller, initImageId: str
177
177
  handleClosePresetModal: () => void;
178
178
  handleOpenPresetModalMobile: () => void;
179
179
  handleClosePresetModalMobile: () => void;
180
- handleCreatePresetMobile: () => void;
180
+ handleCreatePresetMobile: () => Promise<void>;
181
181
  setPresetName: import("react").Dispatch<import("react").SetStateAction<string>>;
182
182
  handleNameChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
183
183
  isRenameModalOpen: boolean;
@@ -251,34 +251,47 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
251
251
  const handleCreatePreset = useCallback(async () => {
252
252
  if (!controller)
253
253
  return;
254
+ // The current adjustment state from the history hook
254
255
  const currentAdjustments = { ...currentAdjustmentsState };
255
256
  try {
256
- const newPreset = await controller.createPreset(firebaseUid, presetName, currentAdjustments);
257
- if (newPreset) {
258
- // Add the new preset returned from the API to our local state
259
- setPresets(prevPresets => [...prevPresets, newPreset]);
257
+ // Call the controller, which now calls the real API
258
+ const newPresetFromApi = await controller.createPreset(firebaseUid, presetName, currentAdjustments);
259
+ // If the API call was successful and returned a preset...
260
+ if (newPresetFromApi) {
261
+ // ...add the new preset from the API response to our local state
262
+ setPresets(prevPresets => [...prevPresets, newPresetFromApi]);
260
263
  }
261
264
  }
262
265
  catch (error) {
263
266
  console.error("Failed to create preset:", error);
267
+ // Optionally: show an error message to the user here
264
268
  }
265
- console.log("Creating preset:", presetName);
266
- const newPreset = { id: `preset${presets.length + 1}`, name: presetName };
267
- setPresets(prevPresets => [...prevPresets, newPreset]);
269
+ // Close the modal and show a confirmation
268
270
  setIsPresetCreated(true);
269
271
  handleClosePresetModal();
270
- setTimeout(() => setIsPresetCreated(false), 1000);
272
+ setTimeout(() => setIsPresetCreated(false), 1000); // Hide confirmation after 1s
271
273
  }, [controller, presetName, currentAdjustmentsState, firebaseUid]);
272
274
  const handleOpenPresetModalMobile = () => { setIsPresetCreated(false); setPresetModalOpenMobile(true); };
273
275
  const handleClosePresetModalMobile = () => setPresetModalOpenMobile(false);
274
- const handleCreatePresetMobile = () => {
276
+ const handleCreatePresetMobile = useCallback(async () => {
277
+ if (!controller)
278
+ return;
275
279
  console.log("Creating mobile preset:", presetName);
276
- const newPreset = { id: `preset${presets.length + 1}`, name: presetName };
277
- setPresets(prevPresets => [...prevPresets, newPreset]);
280
+ const currentAdjustments = { ...currentAdjustmentsState };
281
+ try {
282
+ // RE-USE THE SAME LOGIC AS THE DESKTOP VERSION
283
+ const newPresetFromApi = await controller.createPreset(firebaseUid, presetName, currentAdjustments);
284
+ if (newPresetFromApi) {
285
+ setPresets(prevPresets => [...prevPresets, newPresetFromApi]);
286
+ }
287
+ }
288
+ catch (error) {
289
+ console.error("Failed to create mobile preset:", error);
290
+ }
278
291
  setIsPresetCreated(true);
279
292
  handleClosePresetModalMobile();
280
293
  setTimeout(() => setIsPresetCreated(false), 1000);
281
- };
294
+ }, [controller, presetName, currentAdjustmentsState, firebaseUid]);
282
295
  const handleNameChange = (event) => setPresetName(event.target.value);
283
296
  // Watermark Handlers
284
297
  const handleOpenWatermarkView = () => setIsCreatingWatermark(true);
@@ -22,7 +22,7 @@ export interface ControllerBulk {
22
22
  deletePreset(firebaseUid: string, presetId: string): Promise<void>;
23
23
  }
24
24
  export declare function useHonchoEditorBulk(controller: Controller, eventID: string, firebaseUid: string): {
25
- imageCollection: PhotoData[];
25
+ imageData: PhotoData[];
26
26
  isLoading: boolean;
27
27
  error: string | null;
28
28
  selectedIds: string[];
@@ -1,8 +1,8 @@
1
1
  'use client';
2
- import { useState, useCallback, useEffect } from 'react';
2
+ import { useState, useCallback, useEffect, useMemo } from 'react';
3
3
  import { useAdjustmentHistoryBatch } from '../useAdjustmentHistoryBatch';
4
4
  // Helper function to map the API response to the format our UI component needs
5
- const mapGalleryToPhotoData = (gallery) => {
5
+ const mapGalleryToPhotoData = (gallery, selectedIds) => {
6
6
  return {
7
7
  key: gallery.id,
8
8
  src: gallery.raw_thumbnail?.path ? gallery.raw_thumbnail.path : gallery.thumbnail?.path,
@@ -10,7 +10,7 @@ const mapGalleryToPhotoData = (gallery) => {
10
10
  width: gallery.thumbnail?.width,
11
11
  height: gallery.thumbnail?.height,
12
12
  alt: gallery.id || 'gallery image',
13
- isSelected: false, // Default to not selected
13
+ isSelected: selectedIds.includes(gallery.id),
14
14
  adjustments: gallery.editor_config?.color_adjustment,
15
15
  };
16
16
  };
@@ -45,10 +45,18 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
45
45
  const [isLoading, setIsLoading] = useState(true);
46
46
  const [error, setError] = useState(null);
47
47
  const [selectedBulkPreset, setSelectedBulkPreset] = useState('preset1');
48
+ const imageData = useMemo(() => {
49
+ return imageCollection.map(item => {
50
+ return mapGalleryToPhotoData(item, selectedIds);
51
+ }).map(item => {
52
+ const adjustment = currentBatch.allImages[item.key];
53
+ return adjustment ? { ...item, ...adjustment } : item;
54
+ });
55
+ }, [imageCollection, selectedIds, currentBatch.allImages]);
48
56
  const handleBackCallbackBulk = useCallback(() => {
49
- const lastSelectedId = selectedIds.length > 0 ? selectedIds[selectedIds.length - 1] : eventID;
57
+ const lastSelectedId = selectedIds.length > 0 ? selectedIds[selectedIds.length - 1] : "";
50
58
  controller.handleBack(firebaseUid, lastSelectedId);
51
- }, [controller, firebaseUid, selectedIds, eventID]);
59
+ }, [controller, firebaseUid, selectedIds]);
52
60
  const handleSelectBulkPreset = (event) => setSelectedBulkPreset(event.target.value);
53
61
  // This factory creates functions that adjust a value for all selected images
54
62
  const createRelativeAdjuster = useCallback((key, amount) => () => {
@@ -110,9 +118,9 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
110
118
  setError(null);
111
119
  controller.getImageList(firebaseUid, eventID, 1)
112
120
  .then(response => {
121
+ // TODO need do pagination for this one
113
122
  batchActions.syncAdjustment(response.gallery.map(mapToImageAdjustmentConfig));
114
- const mappedData = response.gallery.map(mapGalleryToPhotoData);
115
- setImageCollection(mappedData);
123
+ setImageCollection(response.gallery);
116
124
  })
117
125
  .catch(err => {
118
126
  console.error("Failed to fetch image list:", err);
@@ -123,21 +131,8 @@ export function useHonchoEditorBulk(controller, eventID, firebaseUid) {
123
131
  });
124
132
  }
125
133
  }, [eventID, firebaseUid, controller]);
126
- useEffect(() => {
127
- // react the changes in the batch state
128
- if (currentBatch.allImages) {
129
- setImageCollection((current) => {
130
- const updated = current.map((image) => {
131
- const adjustment = currentBatch.allImages[image.key];
132
- return adjustment ? { ...image, ...adjustment } : image;
133
- });
134
- return updated;
135
- });
136
- console.log("Adjustment changed detected");
137
- }
138
- }, [currentBatch.allImages]);
139
134
  return {
140
- imageCollection,
135
+ imageData,
141
136
  isLoading,
142
137
  error,
143
138
  selectedIds,
package/dist/index.d.ts CHANGED
@@ -21,10 +21,8 @@ export { default as HWatermarkView } from './components/editor/HWatermarkView';
21
21
  export { default as HModalMobile } from './components/editor/HModalMobile';
22
22
  export { default as HPresetOptionsMenu } from './components/editor/HPresetOptionMenu';
23
23
  export { HAlertInternetBox, HAlertCopyBox, HAlertInternetConnectionBox, HAlertPresetSave } from './components/editor/HAlertBox';
24
- export { AlbumImageGallery, ExtendedPhotoData } from './components/editor/GalleryAlbum/AlbumImageGallery';
24
+ export { AlbumImageGallery } from './components/editor/GalleryAlbum/AlbumImageGallery';
25
25
  export { default as GalleryImageItem } from './components/editor/GalleryAlbum/ImageItem';
26
- export { default as SimplifiedAlbumGallery } from './components/editor/GalleryAlbum/SimplifiedAlbumGallery';
27
- export { default as SimplifiedImageItem } from './components/editor/GalleryAlbum/SimplifiedImageItem';
28
26
  export { EditorProvider, useEditorContext } from './lib/context/EditorContext';
29
27
  export { useImageProcessor } from './lib/hooks/useImageProcessor';
30
28
  export { useEditorHeadless } from './lib/hooks/useEditorHeadless';
package/dist/index.js CHANGED
@@ -20,8 +20,6 @@ export { default as HPresetOptionsMenu } from './components/editor/HPresetOption
20
20
  export { HAlertInternetBox, HAlertCopyBox, HAlertInternetConnectionBox, HAlertPresetSave } from './components/editor/HAlertBox';
21
21
  export { AlbumImageGallery } from './components/editor/GalleryAlbum/AlbumImageGallery';
22
22
  export { default as GalleryImageItem } from './components/editor/GalleryAlbum/ImageItem';
23
- export { default as SimplifiedAlbumGallery } from './components/editor/GalleryAlbum/SimplifiedAlbumGallery';
24
- export { default as SimplifiedImageItem } from './components/editor/GalleryAlbum/SimplifiedImageItem';
25
23
  export { EditorProvider, useEditorContext } from './lib/context/EditorContext';
26
24
  export { useImageProcessor } from './lib/hooks/useImageProcessor';
27
25
  export { useEditorHeadless } from './lib/hooks/useEditorHeadless';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yogiswara/honcho-editor-ui",
3
- "version": "2.2.5",
3
+ "version": "2.2.7",
4
4
  "description": "A complete UI component library for the Honcho photo editor.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",