@yogiswara/honcho-editor-ui 2.2.7 → 2.3.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.
|
@@ -10,8 +10,9 @@ export interface Controller {
|
|
|
10
10
|
syncConfig(firebaseUid: string): Promise<void>;
|
|
11
11
|
handleBack(firebaseUid: string, imageID: string): void;
|
|
12
12
|
getPresets(firebaseUid: string): Promise<Preset[]>;
|
|
13
|
-
createPreset(firebaseUid: string, name: string, settings: AdjustmentState): Promise<
|
|
13
|
+
createPreset(firebaseUid: string, name: string, settings: AdjustmentState): Promise<void>;
|
|
14
14
|
deletePreset(firebaseUid: string, presetId: string): Promise<void>;
|
|
15
|
+
updatePreset(firebaseUid: string, data: Preset): Promise<void>;
|
|
15
16
|
}
|
|
16
17
|
export type AdjustmentState = {
|
|
17
18
|
tempScore: number;
|
|
@@ -30,6 +31,19 @@ export type AdjustmentState = {
|
|
|
30
31
|
export type Preset = {
|
|
31
32
|
id: string;
|
|
32
33
|
name: string;
|
|
34
|
+
is_default: boolean;
|
|
35
|
+
temperature: number;
|
|
36
|
+
tint: number;
|
|
37
|
+
saturation: number;
|
|
38
|
+
vibrance: number;
|
|
39
|
+
exposure: number;
|
|
40
|
+
contrast: number;
|
|
41
|
+
highlights: number;
|
|
42
|
+
shadows: number;
|
|
43
|
+
whites: number;
|
|
44
|
+
blacks: number;
|
|
45
|
+
clarity: number;
|
|
46
|
+
sharpness: number;
|
|
33
47
|
};
|
|
34
48
|
export type ImageItem = {
|
|
35
49
|
id: string;
|
|
@@ -255,12 +255,12 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
255
255
|
const currentAdjustments = { ...currentAdjustmentsState };
|
|
256
256
|
try {
|
|
257
257
|
// Call the controller, which now calls the real API
|
|
258
|
-
|
|
258
|
+
await controller.createPreset(firebaseUid, presetName, currentAdjustments);
|
|
259
259
|
// If the API call was successful and returned a preset...
|
|
260
|
-
if (newPresetFromApi) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
260
|
+
// if (newPresetFromApi) {
|
|
261
|
+
// // ...add the new preset from the API response to our local state
|
|
262
|
+
// setPresets(prevPresets => [...prevPresets, newPresetFromApi]);
|
|
263
|
+
// }
|
|
264
264
|
}
|
|
265
265
|
catch (error) {
|
|
266
266
|
console.error("Failed to create preset:", error);
|
|
@@ -280,10 +280,7 @@ export function useHonchoEditor(controller, initImageId, firebaseUid) {
|
|
|
280
280
|
const currentAdjustments = { ...currentAdjustmentsState };
|
|
281
281
|
try {
|
|
282
282
|
// RE-USE THE SAME LOGIC AS THE DESKTOP VERSION
|
|
283
|
-
|
|
284
|
-
if (newPresetFromApi) {
|
|
285
|
-
setPresets(prevPresets => [...prevPresets, newPresetFromApi]);
|
|
286
|
-
}
|
|
283
|
+
await controller.createPreset(firebaseUid, presetName, currentAdjustments);
|
|
287
284
|
}
|
|
288
285
|
catch (error) {
|
|
289
286
|
console.error("Failed to create mobile preset:", error);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Controller, Preset, AdjustmentState } from './editor/useHonchoEditor';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for the preset hook
|
|
4
|
+
*/
|
|
5
|
+
export interface PresetOptions {
|
|
6
|
+
/** Enable development warnings for debugging */
|
|
7
|
+
devWarnings?: boolean;
|
|
8
|
+
/** Auto-load presets on hook initialization */
|
|
9
|
+
autoLoad?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Information about the current preset state
|
|
13
|
+
*/
|
|
14
|
+
export interface PresetInfo {
|
|
15
|
+
/** Whether presets are currently being loaded */
|
|
16
|
+
isLoading: boolean;
|
|
17
|
+
/** Error message if any operation failed */
|
|
18
|
+
error: string | null;
|
|
19
|
+
/** Number of presets currently managed */
|
|
20
|
+
count: number;
|
|
21
|
+
/** Whether the hook has been initialized */
|
|
22
|
+
isInitialized: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Actions available for preset management
|
|
26
|
+
*/
|
|
27
|
+
export interface PresetActions {
|
|
28
|
+
/** Create a new preset */
|
|
29
|
+
create: (name: string, settings: AdjustmentState) => Promise<Preset | null>;
|
|
30
|
+
/** Rename an existing preset */
|
|
31
|
+
rename: (presetId: string, newName: string) => Promise<boolean>;
|
|
32
|
+
/** Delete a preset */
|
|
33
|
+
delete: (presetId: string) => Promise<boolean>;
|
|
34
|
+
/** Load/refresh presets from backend */
|
|
35
|
+
load: () => Promise<void>;
|
|
36
|
+
/** Find preset that matches the given adjustment state */
|
|
37
|
+
findByAdjustments: (adjustments: AdjustmentState) => Preset | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Return type for the usePreset hook
|
|
41
|
+
*/
|
|
42
|
+
export interface UsePresetReturn {
|
|
43
|
+
/** Current list of presets */
|
|
44
|
+
presets: Preset[];
|
|
45
|
+
/** Information about preset state */
|
|
46
|
+
info: PresetInfo;
|
|
47
|
+
/** Available preset actions */
|
|
48
|
+
actions: PresetActions;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Hook for managing presets with backend communication through Controller.
|
|
52
|
+
*
|
|
53
|
+
* **Key Features:**
|
|
54
|
+
* - **Backend Communication**: All operations go through the provided Controller
|
|
55
|
+
* - **Local State Management**: Maintains local preset list for UI performance
|
|
56
|
+
* - **CRUD Operations**: Create, rename, delete, and list presets
|
|
57
|
+
* - **Error Handling**: Provides error states for failed operations
|
|
58
|
+
* - **Auto-loading**: Optional automatic preset loading on initialization
|
|
59
|
+
*
|
|
60
|
+
* **Typical Usage:**
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const { presets, actions, info } = usePreset(controller, firebaseUid, { autoLoad: true });
|
|
63
|
+
*
|
|
64
|
+
* // Create preset
|
|
65
|
+
* const newPreset = await actions.create('My Preset', adjustmentState);
|
|
66
|
+
*
|
|
67
|
+
* // Rename preset
|
|
68
|
+
* const success = await actions.rename(presetId, 'New Name');
|
|
69
|
+
*
|
|
70
|
+
* // Delete preset
|
|
71
|
+
* const deleted = await actions.delete(presetId);
|
|
72
|
+
*
|
|
73
|
+
* // Manual reload
|
|
74
|
+
* await actions.load();
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @param controller - Backend controller for API communication
|
|
78
|
+
* @param firebaseUid - User identifier for backend operations
|
|
79
|
+
* @param options - Configuration options
|
|
80
|
+
* @returns Object with presets, info, and actions
|
|
81
|
+
*/
|
|
82
|
+
export declare function usePreset(controller: Controller | null, firebaseUid: string, options?: PresetOptions): UsePresetReturn;
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { useState, useCallback, useEffect, useRef, useMemo } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook for managing presets with backend communication through Controller.
|
|
4
|
+
*
|
|
5
|
+
* **Key Features:**
|
|
6
|
+
* - **Backend Communication**: All operations go through the provided Controller
|
|
7
|
+
* - **Local State Management**: Maintains local preset list for UI performance
|
|
8
|
+
* - **CRUD Operations**: Create, rename, delete, and list presets
|
|
9
|
+
* - **Error Handling**: Provides error states for failed operations
|
|
10
|
+
* - **Auto-loading**: Optional automatic preset loading on initialization
|
|
11
|
+
*
|
|
12
|
+
* **Typical Usage:**
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const { presets, actions, info } = usePreset(controller, firebaseUid, { autoLoad: true });
|
|
15
|
+
*
|
|
16
|
+
* // Create preset
|
|
17
|
+
* const newPreset = await actions.create('My Preset', adjustmentState);
|
|
18
|
+
*
|
|
19
|
+
* // Rename preset
|
|
20
|
+
* const success = await actions.rename(presetId, 'New Name');
|
|
21
|
+
*
|
|
22
|
+
* // Delete preset
|
|
23
|
+
* const deleted = await actions.delete(presetId);
|
|
24
|
+
*
|
|
25
|
+
* // Manual reload
|
|
26
|
+
* await actions.load();
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @param controller - Backend controller for API communication
|
|
30
|
+
* @param firebaseUid - User identifier for backend operations
|
|
31
|
+
* @param options - Configuration options
|
|
32
|
+
* @returns Object with presets, info, and actions
|
|
33
|
+
*/
|
|
34
|
+
export function usePreset(controller, firebaseUid, options = {}) {
|
|
35
|
+
// Memoize options to prevent re-renders when object is recreated with same values
|
|
36
|
+
const memoizedOptions = useMemo(() => ({
|
|
37
|
+
devWarnings: options.devWarnings ?? false,
|
|
38
|
+
autoLoad: options.autoLoad ?? false
|
|
39
|
+
}), [options.devWarnings, options.autoLoad]);
|
|
40
|
+
// Core state
|
|
41
|
+
const [presets, setPresets] = useState([]);
|
|
42
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
43
|
+
const [error, setError] = useState(null);
|
|
44
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
45
|
+
// Track controller and firebaseUid changes with stable refs
|
|
46
|
+
const controllerRef = useRef(controller);
|
|
47
|
+
const firebaseUidRef = useRef(firebaseUid);
|
|
48
|
+
// Only update refs when values actually change
|
|
49
|
+
if (controllerRef.current !== controller) {
|
|
50
|
+
controllerRef.current = controller;
|
|
51
|
+
}
|
|
52
|
+
if (firebaseUidRef.current !== firebaseUid) {
|
|
53
|
+
firebaseUidRef.current = firebaseUid;
|
|
54
|
+
}
|
|
55
|
+
// Helper function to log debug messages - memoized to prevent re-renders
|
|
56
|
+
const debugLog = useCallback((message, data) => {
|
|
57
|
+
if (memoizedOptions.devWarnings) {
|
|
58
|
+
console.log(`[usePreset] ${message}`, data || '');
|
|
59
|
+
}
|
|
60
|
+
}, [memoizedOptions.devWarnings]);
|
|
61
|
+
// Helper function to handle errors
|
|
62
|
+
const handleError = useCallback((operation, error) => {
|
|
63
|
+
const errorMessage = `Failed to ${operation}: ${error?.message || error}`;
|
|
64
|
+
setError(errorMessage);
|
|
65
|
+
debugLog(`Error in ${operation}`, error);
|
|
66
|
+
return false;
|
|
67
|
+
}, [debugLog]);
|
|
68
|
+
// Load presets from backend
|
|
69
|
+
const load = useCallback(async () => {
|
|
70
|
+
if (!controllerRef.current || !firebaseUidRef.current) {
|
|
71
|
+
debugLog('Load skipped: missing controller or firebaseUid');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
setIsLoading(true);
|
|
75
|
+
setError(null);
|
|
76
|
+
try {
|
|
77
|
+
debugLog('Loading presets from backend...');
|
|
78
|
+
const loadedPresets = await controllerRef.current.getPresets(firebaseUidRef.current);
|
|
79
|
+
setPresets(loadedPresets);
|
|
80
|
+
setIsInitialized(true);
|
|
81
|
+
debugLog('Presets loaded successfully', { count: loadedPresets.length });
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
handleError('load presets', err);
|
|
85
|
+
setPresets([]); // Clear presets on error
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
setIsLoading(false);
|
|
89
|
+
}
|
|
90
|
+
}, [debugLog, handleError]);
|
|
91
|
+
// Fire-and-forget version of load for internal use
|
|
92
|
+
const loadInBackground = useCallback(() => {
|
|
93
|
+
if (!controllerRef.current || !firebaseUidRef.current) {
|
|
94
|
+
debugLog('Background load skipped: missing controller or firebaseUid');
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
debugLog('Background loading presets...');
|
|
98
|
+
// Don't set loading state for background operations
|
|
99
|
+
controllerRef.current.getPresets(firebaseUidRef.current)
|
|
100
|
+
.then(loadedPresets => {
|
|
101
|
+
setPresets(loadedPresets);
|
|
102
|
+
if (!isInitialized) {
|
|
103
|
+
setIsInitialized(true);
|
|
104
|
+
}
|
|
105
|
+
debugLog('Background presets loaded successfully', { count: loadedPresets.length });
|
|
106
|
+
})
|
|
107
|
+
.catch(err => {
|
|
108
|
+
debugLog('Background load failed:', err);
|
|
109
|
+
// Don't set error state for background operations
|
|
110
|
+
});
|
|
111
|
+
}, [debugLog, isInitialized]);
|
|
112
|
+
// Create a new preset
|
|
113
|
+
const create = useCallback(async (name, settings) => {
|
|
114
|
+
if (!controllerRef.current || !firebaseUidRef.current) {
|
|
115
|
+
debugLog('Create skipped: missing controller or firebaseUid');
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
if (!name.trim()) {
|
|
119
|
+
setError('Preset name cannot be empty');
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
// Check for duplicate names
|
|
123
|
+
if (presets.some(p => p.name.toLowerCase() === name.toLowerCase())) {
|
|
124
|
+
setError('A preset with this name already exists');
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
setIsLoading(true);
|
|
128
|
+
setError(null);
|
|
129
|
+
try {
|
|
130
|
+
debugLog('Creating preset...', { name, settings });
|
|
131
|
+
// Fire the create request but don't wait for preset data in response
|
|
132
|
+
await controllerRef.current.createPreset(firebaseUidRef.current, name, settings);
|
|
133
|
+
debugLog('Preset creation request completed');
|
|
134
|
+
// Fire and forget: Schedule a delayed refresh to get updated preset list
|
|
135
|
+
setTimeout(() => {
|
|
136
|
+
debugLog('Refreshing presets after create (fire and forget)');
|
|
137
|
+
loadInBackground();
|
|
138
|
+
}, 500); // 500ms delay to allow backend processing
|
|
139
|
+
// Return a minimal success indicator since we don't have the actual preset data
|
|
140
|
+
return { id: 'pending', name, is_default: false };
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
handleError('create preset', err);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
setIsLoading(false);
|
|
148
|
+
}
|
|
149
|
+
}, [presets, debugLog, handleError, loadInBackground]);
|
|
150
|
+
// Rename an existing preset
|
|
151
|
+
const rename = useCallback(async (presetId, newName) => {
|
|
152
|
+
if (!controllerRef.current || !firebaseUidRef.current) {
|
|
153
|
+
debugLog('Rename skipped: missing controller or firebaseUid');
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
if (!newName.trim()) {
|
|
157
|
+
setError('Preset name cannot be empty');
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
const existingPreset = presets.find(p => p.id === presetId);
|
|
161
|
+
if (!existingPreset) {
|
|
162
|
+
setError('Preset not found');
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
// Check for duplicate names (excluding the current preset)
|
|
166
|
+
if (presets.some(p => p.id !== presetId && p.name.toLowerCase() === newName.toLowerCase())) {
|
|
167
|
+
setError('A preset with this name already exists');
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
setIsLoading(true);
|
|
171
|
+
setError(null);
|
|
172
|
+
try {
|
|
173
|
+
debugLog('Renaming preset...', { presetId, oldName: existingPreset.name, newName });
|
|
174
|
+
const updatedPreset = { ...existingPreset, name: newName };
|
|
175
|
+
await controllerRef.current.updatePreset(firebaseUidRef.current, updatedPreset);
|
|
176
|
+
// Update local state
|
|
177
|
+
setPresets(prev => prev.map(p => p.id === presetId ? updatedPreset : p));
|
|
178
|
+
debugLog('Preset renamed successfully');
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
handleError('rename preset', err);
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
setIsLoading(false);
|
|
187
|
+
}
|
|
188
|
+
}, [presets, debugLog, handleError]);
|
|
189
|
+
// Delete a preset
|
|
190
|
+
const deletePreset = useCallback(async (presetId) => {
|
|
191
|
+
if (!controllerRef.current || !firebaseUidRef.current) {
|
|
192
|
+
debugLog('Delete skipped: missing controller or firebaseUid');
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
const existingPreset = presets.find(p => p.id === presetId);
|
|
196
|
+
if (!existingPreset) {
|
|
197
|
+
setError('Preset not found');
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
setIsLoading(true);
|
|
201
|
+
setError(null);
|
|
202
|
+
try {
|
|
203
|
+
debugLog('Deleting preset...', { presetId, name: existingPreset.name });
|
|
204
|
+
await controllerRef.current.deletePreset(firebaseUidRef.current, presetId);
|
|
205
|
+
// Remove from local state
|
|
206
|
+
setPresets(prev => prev.filter(p => p.id !== presetId));
|
|
207
|
+
debugLog('Preset deleted successfully');
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
handleError('delete preset', err);
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
setIsLoading(false);
|
|
216
|
+
}
|
|
217
|
+
}, [presets, debugLog, handleError]);
|
|
218
|
+
// Find preset that matches the given adjustment state
|
|
219
|
+
const findByAdjustments = useCallback((adjustments) => {
|
|
220
|
+
// Helper function to normalize adjustment values (treat null/undefined as 0)
|
|
221
|
+
const normalizeValue = (value) => {
|
|
222
|
+
return value ?? 0;
|
|
223
|
+
};
|
|
224
|
+
// Helper function to convert Preset to AdjustmentState for comparison
|
|
225
|
+
const presetToAdjustmentState = (preset) => {
|
|
226
|
+
return {
|
|
227
|
+
tempScore: normalizeValue(preset.temperature),
|
|
228
|
+
tintScore: normalizeValue(preset.tint),
|
|
229
|
+
vibranceScore: normalizeValue(preset.vibrance),
|
|
230
|
+
saturationScore: normalizeValue(preset.saturation),
|
|
231
|
+
exposureScore: normalizeValue(preset.exposure),
|
|
232
|
+
highlightsScore: normalizeValue(preset.highlights),
|
|
233
|
+
shadowsScore: normalizeValue(preset.shadows),
|
|
234
|
+
whitesScore: normalizeValue(preset.whites),
|
|
235
|
+
blacksScore: normalizeValue(preset.blacks),
|
|
236
|
+
contrastScore: normalizeValue(preset.contrast),
|
|
237
|
+
clarityScore: normalizeValue(preset.clarity),
|
|
238
|
+
sharpnessScore: normalizeValue(preset.sharpness)
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
// Helper function to compare two adjustment states
|
|
242
|
+
const adjustmentsMatch = (presetSettings, current) => {
|
|
243
|
+
const keys = [
|
|
244
|
+
'tempScore', 'tintScore', 'vibranceScore', 'saturationScore',
|
|
245
|
+
'exposureScore', 'highlightsScore', 'shadowsScore', 'whitesScore',
|
|
246
|
+
'blacksScore', 'contrastScore', 'clarityScore', 'sharpnessScore'
|
|
247
|
+
];
|
|
248
|
+
return keys.every(key => normalizeValue(presetSettings[key]) === normalizeValue(current[key]));
|
|
249
|
+
};
|
|
250
|
+
debugLog('Finding preset by adjustments...', adjustments);
|
|
251
|
+
// Find preset that matches the current adjustments
|
|
252
|
+
const matchingPreset = presets.find(preset => {
|
|
253
|
+
const presetAdjustments = presetToAdjustmentState(preset);
|
|
254
|
+
return adjustmentsMatch(presetAdjustments, adjustments);
|
|
255
|
+
});
|
|
256
|
+
if (matchingPreset) {
|
|
257
|
+
debugLog('Found matching preset:', matchingPreset);
|
|
258
|
+
return matchingPreset;
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
debugLog('No matching preset found');
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
}, [presets, debugLog]);
|
|
265
|
+
// Auto-load presets on initialization - stable dependencies
|
|
266
|
+
useEffect(() => {
|
|
267
|
+
if (memoizedOptions.autoLoad && controller && firebaseUid && !isInitialized) {
|
|
268
|
+
debugLog('Auto-loading presets...');
|
|
269
|
+
load();
|
|
270
|
+
}
|
|
271
|
+
}, [memoizedOptions.autoLoad, controller, firebaseUid, isInitialized, load, debugLog]);
|
|
272
|
+
// Clear state when controller or firebaseUid changes
|
|
273
|
+
useEffect(() => {
|
|
274
|
+
if (isInitialized) {
|
|
275
|
+
debugLog('Controller or firebaseUid changed, clearing state');
|
|
276
|
+
setPresets([]);
|
|
277
|
+
setError(null);
|
|
278
|
+
setIsInitialized(false);
|
|
279
|
+
}
|
|
280
|
+
}, [controller, firebaseUid, isInitialized, debugLog]);
|
|
281
|
+
// Preset info object - memoized to prevent re-renders
|
|
282
|
+
const info = useMemo(() => ({
|
|
283
|
+
isLoading,
|
|
284
|
+
error,
|
|
285
|
+
count: presets.length,
|
|
286
|
+
isInitialized
|
|
287
|
+
}), [isLoading, error, presets.length, isInitialized]);
|
|
288
|
+
// Actions object - memoized to prevent re-renders when functions don't change
|
|
289
|
+
const actions = useMemo(() => ({
|
|
290
|
+
create,
|
|
291
|
+
rename,
|
|
292
|
+
delete: deletePreset,
|
|
293
|
+
load,
|
|
294
|
+
findByAdjustments
|
|
295
|
+
}), [create, rename, deletePreset, load, findByAdjustments]);
|
|
296
|
+
// Return object - memoized to prevent re-renders when values don't change
|
|
297
|
+
return useMemo(() => ({
|
|
298
|
+
presets,
|
|
299
|
+
info,
|
|
300
|
+
actions
|
|
301
|
+
}), [presets, info, actions]);
|
|
302
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export { useImageProcessor } from './lib/hooks/useImageProcessor';
|
|
|
28
28
|
export { useEditorHeadless } from './lib/hooks/useEditorHeadless';
|
|
29
29
|
export { useAdjustmentHistory, type UseAdjustmentHistoryReturn, type HistoryInfo, type HistoryActions, type HistoryConfig } from './hooks/useAdjustmentHistory';
|
|
30
30
|
export { useAdjustmentHistoryBatch, type UseAdjustmentHistoryBatchReturn, type BatchAdjustmentState, type ImageAdjustmentConfig, type BatchHistoryInfo, type BatchHistoryActions, type BatchHistoryConfig } from './hooks/useAdjustmentHistoryBatch';
|
|
31
|
+
export { usePreset, type UsePresetReturn, type PresetInfo, type PresetActions, type PresetOptions } from './hooks/usePreset';
|
|
31
32
|
export { default as useColors } from './themes/colors';
|
|
32
33
|
export { default as useHonchoTypography } from './themes/honchoTheme';
|
|
33
34
|
export { default as useIsMobile } from './utils/isMobile';
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,8 @@ export { useEditorHeadless } from './lib/hooks/useEditorHeadless';
|
|
|
26
26
|
// --- History Hooks ---
|
|
27
27
|
export { useAdjustmentHistory } from './hooks/useAdjustmentHistory';
|
|
28
28
|
export { useAdjustmentHistoryBatch } from './hooks/useAdjustmentHistoryBatch';
|
|
29
|
+
// --- Preset Hook ---
|
|
30
|
+
export { usePreset } from './hooks/usePreset';
|
|
29
31
|
// --- Theme & Utils ---
|
|
30
32
|
export { default as useColors } from './themes/colors';
|
|
31
33
|
export { default as useHonchoTypography } from './themes/honchoTheme';
|