@yogiswara/honcho-editor-ui 2.10.0 → 2.10.2
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/HSliderColorMobile.js +13 -56
- package/dist/components/editor/HSliderLightMobile.js +19 -84
- package/dist/components/editor/sliderComponents/useSliderEvents.d.ts +2 -0
- package/dist/components/editor/sliderComponents/useSliderEvents.js +28 -0
- package/dist/hooks/demo/HonchoEditorBulkDemo.js +2 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -2
- package/dist/lib/hooks/useEditor.d.ts +1 -1
- package/dist/lib/hooks/useEditor.js +1 -1
- package/dist/lib/hooks/useEditorHeadless.d.ts +2 -2
- package/dist/lib/hooks/useEditorHeadless.js +1 -1
- package/dist/lib/hooks/useImageProcessor.d.ts +5 -2
- package/dist/lib/hooks/useImageProcessor.js +29 -4
- package/dist/services/type.d.ts +7 -1
- package/package.json +1 -1
- package/dist/services/base.d.ts +0 -57
- package/dist/services/base.js +0 -243
|
@@ -2,9 +2,14 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { Stack, Slider, Typography, TextField } from "@mui/material";
|
|
3
3
|
import useHonchoTypography from "../../themes/honchoTheme";
|
|
4
4
|
import useColors from '../../themes/colors';
|
|
5
|
+
import useSliderEvents from "../editor/sliderComponents/useSliderEvents";
|
|
5
6
|
export default function HSliderColorMobile(props) {
|
|
6
7
|
const typography = useHonchoTypography();
|
|
7
8
|
const colors = useColors();
|
|
9
|
+
const tempSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
10
|
+
const tintSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
11
|
+
const vibranceSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
12
|
+
const saturationSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
8
13
|
const blueScale = '#292bc0'; // Blue color on left
|
|
9
14
|
const yellowScale = '#dfdc28'; // Yellow color on right
|
|
10
15
|
const greenScale = '#00ff04';
|
|
@@ -72,7 +77,7 @@ export default function HSliderColorMobile(props) {
|
|
|
72
77
|
color: colors.surface,
|
|
73
78
|
fontSize: "14px",
|
|
74
79
|
},
|
|
75
|
-
} })] }), _jsx(Slider, { sx: {
|
|
80
|
+
} })] }), _jsx(Slider, { ref: tempSliderRef, sx: {
|
|
76
81
|
width: "100%",
|
|
77
82
|
color: colors.surface,
|
|
78
83
|
'& .MuiSlider-rail': {
|
|
@@ -86,19 +91,7 @@ export default function HSliderColorMobile(props) {
|
|
|
86
91
|
'& .MuiSlider-thumb': {
|
|
87
92
|
boxShadow: 'none',
|
|
88
93
|
}
|
|
89
|
-
}, size: "small", value: props.tempScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onTempChange("tempScore", newValue), onDoubleClick: () => props.onTempChange("tempScore", 0),
|
|
90
|
-
if (!props.isBatchMode) {
|
|
91
|
-
props.onDragStart();
|
|
92
|
-
}
|
|
93
|
-
}, onMouseUp: () => {
|
|
94
|
-
props.onDragEnd();
|
|
95
|
-
}, onTouchStart: () => {
|
|
96
|
-
if (!props.isBatchMode) {
|
|
97
|
-
props.onDragStart();
|
|
98
|
-
}
|
|
99
|
-
}, onTouchEnd: () => {
|
|
100
|
-
props.onDragEnd();
|
|
101
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px', '&:focus-within .MuiFilledInput-input': focusedInputStyle }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onTintChange("tintScore", 0), children: "Tint" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.tintScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onTintChange("tintScore", val)), sx: {
|
|
94
|
+
}, size: "small", value: props.tempScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onTempChange("tempScore", newValue), onDoubleClick: () => props.onTempChange("tempScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px', '&:focus-within .MuiFilledInput-input': focusedInputStyle }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onTintChange("tintScore", 0), children: "Tint" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.tintScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onTintChange("tintScore", val)), sx: {
|
|
102
95
|
width: "40px",
|
|
103
96
|
alignItems: "center",
|
|
104
97
|
textAlign: "right",
|
|
@@ -128,7 +121,7 @@ export default function HSliderColorMobile(props) {
|
|
|
128
121
|
color: colors.surface,
|
|
129
122
|
fontSize: "14px",
|
|
130
123
|
},
|
|
131
|
-
} })] }), _jsx(Slider, { sx: {
|
|
124
|
+
} })] }), _jsx(Slider, { ref: tintSliderRef, sx: {
|
|
132
125
|
width: "100%",
|
|
133
126
|
color: colors.surface,
|
|
134
127
|
'& .MuiSlider-rail': {
|
|
@@ -142,19 +135,7 @@ export default function HSliderColorMobile(props) {
|
|
|
142
135
|
'& .MuiSlider-thumb': {
|
|
143
136
|
boxShadow: 'none',
|
|
144
137
|
}
|
|
145
|
-
}, size: "small", value: props.tintScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onTintChange("tintScore", newValue), onDoubleClick: () => props.onTintChange("tintScore", 0),
|
|
146
|
-
if (!props.isBatchMode) {
|
|
147
|
-
props.onDragStart();
|
|
148
|
-
}
|
|
149
|
-
}, onMouseUp: () => {
|
|
150
|
-
props.onDragEnd();
|
|
151
|
-
}, onTouchStart: () => {
|
|
152
|
-
if (!props.isBatchMode) {
|
|
153
|
-
props.onDragStart();
|
|
154
|
-
}
|
|
155
|
-
}, onTouchEnd: () => {
|
|
156
|
-
props.onDragEnd();
|
|
157
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px', '&:focus-within .MuiFilledInput-input': focusedInputStyle }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onVibranceChange("vibranceScore", 0), children: "Vibrance" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.vibranceScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onVibranceChange("vibranceScore", val)), sx: {
|
|
138
|
+
}, size: "small", value: props.tintScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onTintChange("tintScore", newValue), onDoubleClick: () => props.onTintChange("tintScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px', '&:focus-within .MuiFilledInput-input': focusedInputStyle }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onVibranceChange("vibranceScore", 0), children: "Vibrance" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.vibranceScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onVibranceChange("vibranceScore", val)), sx: {
|
|
158
139
|
width: "40px",
|
|
159
140
|
alignItems: "center",
|
|
160
141
|
textAlign: "right",
|
|
@@ -184,7 +165,7 @@ export default function HSliderColorMobile(props) {
|
|
|
184
165
|
color: colors.surface,
|
|
185
166
|
fontSize: "14px",
|
|
186
167
|
},
|
|
187
|
-
} })] }), _jsx(Slider, { sx: {
|
|
168
|
+
} })] }), _jsx(Slider, { ref: vibranceSliderRef, sx: {
|
|
188
169
|
width: "100%",
|
|
189
170
|
color: colors.surface,
|
|
190
171
|
'& .MuiSlider-rail': {
|
|
@@ -198,19 +179,7 @@ export default function HSliderColorMobile(props) {
|
|
|
198
179
|
'& .MuiSlider-thumb': {
|
|
199
180
|
boxShadow: 'none',
|
|
200
181
|
}
|
|
201
|
-
}, size: "small", value: props.vibranceScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onVibranceChange("vibranceScore", newValue), onDoubleClick: () => props.onVibranceChange("vibranceScore", 0),
|
|
202
|
-
if (!props.isBatchMode) {
|
|
203
|
-
props.onDragStart();
|
|
204
|
-
}
|
|
205
|
-
}, onMouseUp: () => {
|
|
206
|
-
props.onDragEnd();
|
|
207
|
-
}, onTouchStart: () => {
|
|
208
|
-
if (!props.isBatchMode) {
|
|
209
|
-
props.onDragStart();
|
|
210
|
-
}
|
|
211
|
-
}, onTouchEnd: () => {
|
|
212
|
-
props.onDragEnd();
|
|
213
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px', '&:focus-within .MuiFilledInput-input': focusedInputStyle }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onSaturationChange("saturationScore", 0), children: "Saturation" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.saturationScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onSaturationChange("saturationScore", val)), sx: {
|
|
182
|
+
}, size: "small", value: props.vibranceScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onVibranceChange("vibranceScore", newValue), onDoubleClick: () => props.onVibranceChange("vibranceScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px', '&:focus-within .MuiFilledInput-input': focusedInputStyle }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onSaturationChange("saturationScore", 0), children: "Saturation" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.saturationScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onSaturationChange("saturationScore", val)), sx: {
|
|
214
183
|
width: "40px",
|
|
215
184
|
alignItems: "center",
|
|
216
185
|
textAlign: "right",
|
|
@@ -240,7 +209,7 @@ export default function HSliderColorMobile(props) {
|
|
|
240
209
|
color: colors.surface,
|
|
241
210
|
fontSize: "14px",
|
|
242
211
|
},
|
|
243
|
-
} })] }), _jsx(Slider, { sx: {
|
|
212
|
+
} })] }), _jsx(Slider, { ref: saturationSliderRef, sx: {
|
|
244
213
|
width: "100%",
|
|
245
214
|
color: colors.surface,
|
|
246
215
|
'& .MuiSlider-rail': {
|
|
@@ -254,17 +223,5 @@ export default function HSliderColorMobile(props) {
|
|
|
254
223
|
'& .MuiSlider-thumb': {
|
|
255
224
|
boxShadow: 'none',
|
|
256
225
|
}
|
|
257
|
-
}, size: "small", value: props.saturationScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onSaturationChange("saturationScore", newValue), onDoubleClick: () => props.onSaturationChange("saturationScore", 0)
|
|
258
|
-
if (!props.isBatchMode) {
|
|
259
|
-
props.onDragStart();
|
|
260
|
-
}
|
|
261
|
-
}, onMouseUp: () => {
|
|
262
|
-
props.onDragEnd();
|
|
263
|
-
}, onTouchStart: () => {
|
|
264
|
-
if (!props.isBatchMode) {
|
|
265
|
-
props.onDragStart();
|
|
266
|
-
}
|
|
267
|
-
}, onTouchEnd: () => {
|
|
268
|
-
props.onDragEnd();
|
|
269
|
-
} })] }) }));
|
|
226
|
+
}, size: "small", value: props.saturationScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onSaturationChange("saturationScore", newValue), onDoubleClick: () => props.onSaturationChange("saturationScore", 0) })] }) }));
|
|
270
227
|
}
|
|
@@ -2,9 +2,16 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { Stack, Slider, Typography, TextField } from "@mui/material";
|
|
3
3
|
import useHonchoTypography from "../../themes/honchoTheme";
|
|
4
4
|
import useColors from '../../themes/colors';
|
|
5
|
+
import useSliderEvents from "../editor/sliderComponents/useSliderEvents";
|
|
5
6
|
export default function HSliderLightMobile(props) {
|
|
6
7
|
const typography = useHonchoTypography();
|
|
7
8
|
const colors = useColors();
|
|
9
|
+
const exposureSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
10
|
+
const contrastSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
11
|
+
const highlightsSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
12
|
+
const shadowsSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
13
|
+
const whitesSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
14
|
+
const blacksSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
|
|
8
15
|
const formatValue = (value) => {
|
|
9
16
|
if (value > 0)
|
|
10
17
|
return `+${value}`;
|
|
@@ -59,7 +66,7 @@ export default function HSliderLightMobile(props) {
|
|
|
59
66
|
pl: '2px',
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
|
-
} })] }), _jsx(Slider, { sx: {
|
|
69
|
+
} })] }), _jsx(Slider, { ref: exposureSliderRef, sx: {
|
|
63
70
|
width: "100%",
|
|
64
71
|
color: colors.onSurfaceVariant,
|
|
65
72
|
'& .MuiSlider-rail': {
|
|
@@ -74,19 +81,7 @@ export default function HSliderLightMobile(props) {
|
|
|
74
81
|
'& .MuiSlider-thumb:hover': {
|
|
75
82
|
boxShadow: 'none',
|
|
76
83
|
}
|
|
77
|
-
}, size: "small", value: props.exposureScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onExposureChange("exposureScore", newValue), onDoubleClick: () => props.onExposureChange("exposureScore", 0),
|
|
78
|
-
if (!props.isBatchMode) {
|
|
79
|
-
props.onDragStart();
|
|
80
|
-
}
|
|
81
|
-
}, onMouseUp: () => {
|
|
82
|
-
props.onDragEnd();
|
|
83
|
-
}, onTouchStart: () => {
|
|
84
|
-
if (!props.isBatchMode) {
|
|
85
|
-
props.onDragStart();
|
|
86
|
-
}
|
|
87
|
-
}, onTouchEnd: () => {
|
|
88
|
-
props.onDragEnd();
|
|
89
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, children: "Contrast" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.contrastScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onContrastChange("contrastScore", val)), sx: {
|
|
84
|
+
}, size: "small", value: props.exposureScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onExposureChange("exposureScore", newValue), onDoubleClick: () => props.onExposureChange("exposureScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, children: "Contrast" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.contrastScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onContrastChange("contrastScore", val)), sx: {
|
|
90
85
|
width: "40px",
|
|
91
86
|
alignItems: "center",
|
|
92
87
|
textAlign: "right",
|
|
@@ -125,7 +120,7 @@ export default function HSliderLightMobile(props) {
|
|
|
125
120
|
pl: '2px',
|
|
126
121
|
}
|
|
127
122
|
}
|
|
128
|
-
} })] }), _jsx(Slider, { sx: {
|
|
123
|
+
} })] }), _jsx(Slider, { ref: contrastSliderRef, sx: {
|
|
129
124
|
width: "100%",
|
|
130
125
|
color: colors.onSurfaceVariant,
|
|
131
126
|
'& .MuiSlider-rail': {
|
|
@@ -140,19 +135,7 @@ export default function HSliderLightMobile(props) {
|
|
|
140
135
|
'& .MuiSlider-thumb:hover': {
|
|
141
136
|
boxShadow: 'none',
|
|
142
137
|
}
|
|
143
|
-
}, size: "small", value: props.contrastScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onContrastChange("contrastScore", newValue), onDoubleClick: () => props.onContrastChange("contrastScore", 0),
|
|
144
|
-
if (!props.isBatchMode) {
|
|
145
|
-
props.onDragStart();
|
|
146
|
-
}
|
|
147
|
-
}, onMouseUp: () => {
|
|
148
|
-
props.onDragEnd();
|
|
149
|
-
}, onTouchStart: () => {
|
|
150
|
-
if (!props.isBatchMode) {
|
|
151
|
-
props.onDragStart();
|
|
152
|
-
}
|
|
153
|
-
}, onTouchEnd: () => {
|
|
154
|
-
props.onDragEnd();
|
|
155
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onHighlightsChange("highlightsScore", 0), children: "Highlights" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.highlightsScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onHighlightsChange("highlightsScore", val)), sx: {
|
|
138
|
+
}, size: "small", value: props.contrastScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onContrastChange("contrastScore", newValue), onDoubleClick: () => props.onContrastChange("contrastScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onHighlightsChange("highlightsScore", 0), children: "Highlights" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.highlightsScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onHighlightsChange("highlightsScore", val)), sx: {
|
|
156
139
|
width: "40px",
|
|
157
140
|
alignItems: "center",
|
|
158
141
|
textAlign: "right",
|
|
@@ -191,7 +174,7 @@ export default function HSliderLightMobile(props) {
|
|
|
191
174
|
pl: '2px',
|
|
192
175
|
}
|
|
193
176
|
}
|
|
194
|
-
} })] }), _jsx(Slider, { sx: {
|
|
177
|
+
} })] }), _jsx(Slider, { ref: highlightsSliderRef, sx: {
|
|
195
178
|
width: "100%",
|
|
196
179
|
color: colors.onSurfaceVariant,
|
|
197
180
|
'& .MuiSlider-rail': {
|
|
@@ -206,19 +189,7 @@ export default function HSliderLightMobile(props) {
|
|
|
206
189
|
'& .MuiSlider-thumb:hover': {
|
|
207
190
|
boxShadow: 'none',
|
|
208
191
|
}
|
|
209
|
-
}, size: "small", value: props.highlightsScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onHighlightsChange("highlightsScore", newValue), onDoubleClick: () => props.onHighlightsChange("highlightsScore", 0),
|
|
210
|
-
if (!props.isBatchMode) {
|
|
211
|
-
props.onDragStart();
|
|
212
|
-
}
|
|
213
|
-
}, onMouseUp: () => {
|
|
214
|
-
props.onDragEnd();
|
|
215
|
-
}, onTouchStart: () => {
|
|
216
|
-
if (!props.isBatchMode) {
|
|
217
|
-
props.onDragStart();
|
|
218
|
-
}
|
|
219
|
-
}, onTouchEnd: () => {
|
|
220
|
-
props.onDragEnd();
|
|
221
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onShadowsChange("shadowsScore", 0), children: "Shadows" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.shadowScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onShadowsChange("shadowsScore", val)), sx: {
|
|
192
|
+
}, size: "small", value: props.highlightsScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onHighlightsChange("highlightsScore", newValue), onDoubleClick: () => props.onHighlightsChange("highlightsScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onShadowsChange("shadowsScore", 0), children: "Shadows" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.shadowScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onShadowsChange("shadowsScore", val)), sx: {
|
|
222
193
|
width: "40px",
|
|
223
194
|
alignItems: "center",
|
|
224
195
|
textAlign: "right",
|
|
@@ -257,7 +228,7 @@ export default function HSliderLightMobile(props) {
|
|
|
257
228
|
pl: '2px',
|
|
258
229
|
}
|
|
259
230
|
}
|
|
260
|
-
} })] }), _jsx(Slider, { sx: {
|
|
231
|
+
} })] }), _jsx(Slider, { ref: shadowsSliderRef, sx: {
|
|
261
232
|
width: "100%",
|
|
262
233
|
color: colors.onSurfaceVariant,
|
|
263
234
|
'& .MuiSlider-rail': {
|
|
@@ -272,19 +243,7 @@ export default function HSliderLightMobile(props) {
|
|
|
272
243
|
'& .MuiSlider-thumb:hover': {
|
|
273
244
|
boxShadow: 'none',
|
|
274
245
|
}
|
|
275
|
-
}, size: "small", value: props.shadowScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onShadowsChange("shadowsScore", newValue), onDoubleClick: () => props.onShadowsChange("shadowsScore", 0),
|
|
276
|
-
if (!props.isBatchMode) {
|
|
277
|
-
props.onDragStart();
|
|
278
|
-
}
|
|
279
|
-
}, onMouseUp: () => {
|
|
280
|
-
props.onDragEnd();
|
|
281
|
-
}, onTouchStart: () => {
|
|
282
|
-
if (!props.isBatchMode) {
|
|
283
|
-
props.onDragStart();
|
|
284
|
-
}
|
|
285
|
-
}, onTouchEnd: () => {
|
|
286
|
-
props.onDragEnd();
|
|
287
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onWhitesChange("whitesScore", 0), children: "Whites" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.whiteScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onWhitesChange("whitesScore", val)), sx: {
|
|
246
|
+
}, size: "small", value: props.shadowScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onShadowsChange("shadowsScore", newValue), onDoubleClick: () => props.onShadowsChange("shadowsScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onWhitesChange("whitesScore", 0), children: "Whites" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.whiteScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onWhitesChange("whitesScore", val)), sx: {
|
|
288
247
|
width: "40px",
|
|
289
248
|
alignItems: "center",
|
|
290
249
|
textAlign: "right",
|
|
@@ -323,7 +282,7 @@ export default function HSliderLightMobile(props) {
|
|
|
323
282
|
pl: '2px',
|
|
324
283
|
}
|
|
325
284
|
}
|
|
326
|
-
} })] }), _jsx(Slider, { sx: {
|
|
285
|
+
} })] }), _jsx(Slider, { ref: whitesSliderRef, sx: {
|
|
327
286
|
width: "100%",
|
|
328
287
|
color: colors.onSurfaceVariant,
|
|
329
288
|
'& .MuiSlider-rail': {
|
|
@@ -338,19 +297,7 @@ export default function HSliderLightMobile(props) {
|
|
|
338
297
|
'& .MuiSlider-thumb:hover': {
|
|
339
298
|
boxShadow: 'none',
|
|
340
299
|
}
|
|
341
|
-
}, size: "small", value: props.whiteScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onWhitesChange("whitesScore", newValue), onDoubleClick: () => props.onWhitesChange("whitesScore", 0),
|
|
342
|
-
if (!props.isBatchMode) {
|
|
343
|
-
props.onDragStart();
|
|
344
|
-
}
|
|
345
|
-
}, onMouseUp: () => {
|
|
346
|
-
props.onDragEnd();
|
|
347
|
-
}, onTouchStart: () => {
|
|
348
|
-
if (!props.isBatchMode) {
|
|
349
|
-
props.onDragStart();
|
|
350
|
-
}
|
|
351
|
-
}, onTouchEnd: () => {
|
|
352
|
-
props.onDragEnd();
|
|
353
|
-
} }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onBlacksChange("blacksScore", 0), children: "Blacks" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.blackScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onBlacksChange("blacksScore", val)), sx: {
|
|
300
|
+
}, size: "small", value: props.whiteScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onWhitesChange("whitesScore", newValue), onDoubleClick: () => props.onWhitesChange("whitesScore", 0) }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface }, onDoubleClick: () => props.onBlacksChange("blacksScore", 0), children: "Blacks" }), _jsx(TextField, { InputProps: { readOnly: true }, hiddenLabel: true, id: "filled-hidden-label-small", value: formatValue(props.blackScore), variant: "filled", onChange: (e) => handleInputChange(e, -100, 100, (val) => props.onBlacksChange("blacksScore", val)), sx: {
|
|
354
301
|
width: "40px",
|
|
355
302
|
alignItems: "center",
|
|
356
303
|
textAlign: "right",
|
|
@@ -389,7 +336,7 @@ export default function HSliderLightMobile(props) {
|
|
|
389
336
|
pl: '2px',
|
|
390
337
|
}
|
|
391
338
|
},
|
|
392
|
-
} })] }), _jsx(Slider, { sx: {
|
|
339
|
+
} })] }), _jsx(Slider, { ref: blacksSliderRef, sx: {
|
|
393
340
|
width: "100%",
|
|
394
341
|
color: colors.onSurfaceVariant,
|
|
395
342
|
'& .MuiSlider-rail': {
|
|
@@ -404,17 +351,5 @@ export default function HSliderLightMobile(props) {
|
|
|
404
351
|
'& .MuiSlider-thumb:hover': {
|
|
405
352
|
boxShadow: 'none',
|
|
406
353
|
}
|
|
407
|
-
}, size: "small", value: props.blackScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onBlacksChange("blacksScore", newValue), onDoubleClick: () => props.onBlacksChange("blacksScore", 0)
|
|
408
|
-
if (!props.isBatchMode) {
|
|
409
|
-
props.onDragStart();
|
|
410
|
-
}
|
|
411
|
-
}, onMouseUp: () => {
|
|
412
|
-
props.onDragEnd();
|
|
413
|
-
}, onTouchStart: () => {
|
|
414
|
-
if (!props.isBatchMode) {
|
|
415
|
-
props.onDragStart();
|
|
416
|
-
}
|
|
417
|
-
}, onTouchEnd: () => {
|
|
418
|
-
props.onDragEnd();
|
|
419
|
-
} })] }) }));
|
|
354
|
+
}, size: "small", value: props.blackScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onBlacksChange("blacksScore", newValue), onDoubleClick: () => props.onBlacksChange("blacksScore", 0) })] }) }));
|
|
420
355
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
export default function useSliderEvents(onDragStart, onDragEnd, isBatchMode) {
|
|
3
|
+
const sliderRef = useRef(null);
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const sliderElement = sliderRef.current;
|
|
6
|
+
if (!sliderElement)
|
|
7
|
+
return;
|
|
8
|
+
const handleMouseDown = () => {
|
|
9
|
+
if (!isBatchMode) {
|
|
10
|
+
onDragStart();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const handleMouseUp = () => {
|
|
14
|
+
onDragEnd();
|
|
15
|
+
};
|
|
16
|
+
sliderElement.addEventListener("mousedown", handleMouseDown);
|
|
17
|
+
sliderElement.addEventListener("mouseup", handleMouseUp);
|
|
18
|
+
sliderElement.addEventListener("touchstart", handleMouseDown);
|
|
19
|
+
sliderElement.addEventListener("touchend", handleMouseUp);
|
|
20
|
+
return () => {
|
|
21
|
+
sliderElement.removeEventListener("mousedown", handleMouseDown);
|
|
22
|
+
sliderElement.removeEventListener("mouseup", handleMouseUp);
|
|
23
|
+
sliderElement.removeEventListener("touchstart", handleMouseDown);
|
|
24
|
+
sliderElement.removeEventListener("touchend", handleMouseUp);
|
|
25
|
+
};
|
|
26
|
+
}, [onDragStart, onDragEnd, isBatchMode]);
|
|
27
|
+
return sliderRef; // Return the ref to be attached to the slider
|
|
28
|
+
}
|
|
@@ -264,7 +264,8 @@ const ImageCard = React.memo(({ image, onToggleSelection }) => {
|
|
|
264
264
|
photoSrc: image.src,
|
|
265
265
|
adjustments: image.adjustments,
|
|
266
266
|
enableEditor: shouldLoadImage && isInView, // Only enable when we should load the image AND it's in view
|
|
267
|
-
abortSignal: currentAbortSignalRef.current // Use stable abort signal
|
|
267
|
+
abortSignal: currentAbortSignalRef.current, // Use stable abort signal
|
|
268
|
+
frame: null,
|
|
268
269
|
}), [image.key, image.src, image.adjustments, shouldLoadImage, isInView]);
|
|
269
270
|
// Only call useImageProcessor when the card is visible AND we should load the image AND it's in view
|
|
270
271
|
const { processedImageSrc, isProcessingComplete, cancelProcessing, isProcessing } = useImageProcessor(imageProcessorParams);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { HonchoEditorBulkDemo } from './hooks/demo/HonchoEditorBulkDemo';
|
|
2
|
+
export { HonchoEditorSingleCleanDemo } from './hooks/demo/HonchoEditorSingleCleanDemo';
|
|
1
3
|
export { useHonchoEditorSingle } from './hooks/editor/useHonchoEditorSingle';
|
|
2
4
|
export { useHonchoEditorBulk } from './hooks/editor/useHonchoEditorBulk';
|
|
3
5
|
export type { Controller, AdjustmentState, Preset, ImageItem, ColorAdjustment, CreateEditorTaskRequest, EditorHistoryEntry, GetGalleryUpdateTimestampResponse, GetHistoryResponse, } from './hooks/editor/type';
|
|
@@ -37,3 +39,4 @@ export { usePaging, type UsePagingReturn, type PagingInfo, type PagingActions, t
|
|
|
37
39
|
export { default as useColors } from './themes/colors';
|
|
38
40
|
export { default as useHonchoTypography } from './themes/honchoTheme';
|
|
39
41
|
export { default as useIsMobile } from './utils/isMobile';
|
|
42
|
+
export { default as useSliderEvents } from '../src/components/editor/sliderComponents/useSliderEvents';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// START: delete later
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export { HonchoEditorBulkDemo } from './hooks/demo/HonchoEditorBulkDemo';
|
|
3
|
+
export { HonchoEditorSingleCleanDemo } from './hooks/demo/HonchoEditorSingleCleanDemo';
|
|
4
4
|
// END
|
|
5
5
|
export { useHonchoEditorSingle } from './hooks/editor/useHonchoEditorSingle';
|
|
6
6
|
export { useHonchoEditorBulk } from './hooks/editor/useHonchoEditorBulk';
|
|
@@ -42,3 +42,4 @@ export { usePaging } from './hooks/usePaging';
|
|
|
42
42
|
export { default as useColors } from './themes/colors';
|
|
43
43
|
export { default as useHonchoTypography } from './themes/honchoTheme';
|
|
44
44
|
export { default as useIsMobile } from './utils/isMobile';
|
|
45
|
+
export { default as useSliderEvents } from '../src/components/editor/sliderComponents/useSliderEvents';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
|
-
import { useEditorContext } from '
|
|
3
|
+
import { useEditorContext } from '../../lib/context/EditorContext';
|
|
4
4
|
/**
|
|
5
5
|
* Lightweight hook for components to request image processing
|
|
6
6
|
* Uses the global editor instance via context
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdjustmentValues } from '
|
|
1
|
+
import type { AdjustmentValues, HonchoEditor } from '../../lib/editor/honcho-editor';
|
|
2
2
|
declare global {
|
|
3
3
|
interface Window {
|
|
4
4
|
HonchoEditor: new () => any;
|
|
@@ -22,7 +22,7 @@ interface UseEditorHeadlessOptions {
|
|
|
22
22
|
wasmUrl?: string;
|
|
23
23
|
}
|
|
24
24
|
export declare function useEditorHeadless(options?: UseEditorHeadlessOptions): {
|
|
25
|
-
editor:
|
|
25
|
+
editor: HonchoEditor | null;
|
|
26
26
|
isReady: boolean;
|
|
27
27
|
error: Error | null;
|
|
28
28
|
processImage: (task: EditorTask) => Promise<EditorResponse>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
3
|
-
import { loadImageAsFile } from '
|
|
3
|
+
import { loadImageAsFile } from '../../utils/imageLoader';
|
|
4
4
|
export function useEditorHeadless(options = {}) {
|
|
5
5
|
const { scriptUrl = '/honcho-photo-editor.js', wasmUrl = '/honcho-photo-editor.wasm' } = options;
|
|
6
6
|
const editorRef = useRef(null);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdjustmentValues } from '
|
|
1
|
+
import type { AdjustmentValues } from '../../lib/editor/honcho-editor';
|
|
2
2
|
interface UseImageProcessorProps {
|
|
3
3
|
photoId: string;
|
|
4
4
|
photoSrc: string;
|
|
@@ -6,10 +6,13 @@ interface UseImageProcessorProps {
|
|
|
6
6
|
adjustments?: Partial<AdjustmentValues>;
|
|
7
7
|
frame: string | null;
|
|
8
8
|
priority?: 'high' | 'low';
|
|
9
|
+
abortSignal?: AbortSignal;
|
|
9
10
|
}
|
|
10
11
|
interface UseImageProcessorReturn {
|
|
11
12
|
processedImageSrc: string;
|
|
12
13
|
isProcessingComplete: boolean;
|
|
14
|
+
cancelProcessing: () => void;
|
|
15
|
+
isProcessing: boolean;
|
|
13
16
|
}
|
|
14
|
-
export declare function useImageProcessor({ photoId, photoSrc, enableEditor, adjustments, frame, priority, }: UseImageProcessorProps): UseImageProcessorReturn;
|
|
17
|
+
export declare function useImageProcessor({ photoId, photoSrc, enableEditor, adjustments, frame, priority, abortSignal, }: UseImageProcessorProps): UseImageProcessorReturn;
|
|
15
18
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
2
|
-
import { useEditorHighPriority, useEditorLowPriority } from '
|
|
1
|
+
import { useState, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { useEditorHighPriority, useEditorLowPriority } from '../../lib/hooks/useEditor';
|
|
3
3
|
const initAdjustments = {
|
|
4
4
|
temperature: 0,
|
|
5
5
|
tint: 0,
|
|
@@ -14,13 +14,25 @@ const initAdjustments = {
|
|
|
14
14
|
clarity: 0,
|
|
15
15
|
sharpness: 0
|
|
16
16
|
};
|
|
17
|
-
export function useImageProcessor({ photoId, photoSrc, enableEditor = true, adjustments, frame, priority = 'low', }) {
|
|
17
|
+
export function useImageProcessor({ photoId, photoSrc, enableEditor = true, adjustments, frame, priority = 'low', abortSignal, }) {
|
|
18
18
|
const { processImage, isEditorReady } = priority === 'high'
|
|
19
19
|
? useEditorHighPriority()
|
|
20
20
|
: useEditorLowPriority();
|
|
21
21
|
// State for processed image and processing status
|
|
22
22
|
const [processedImageSrc, setProcessedImageSrc] = useState(photoSrc);
|
|
23
23
|
const [isProcessingComplete, setIsProcessingComplete] = useState(false);
|
|
24
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
25
|
+
// Internal abort controller for this hook
|
|
26
|
+
const abortControllerRef = useRef(null);
|
|
27
|
+
// Function to cancel current processing
|
|
28
|
+
const cancelProcessing = () => {
|
|
29
|
+
if (abortControllerRef.current) {
|
|
30
|
+
abortControllerRef.current.abort();
|
|
31
|
+
abortControllerRef.current = null;
|
|
32
|
+
}
|
|
33
|
+
setIsProcessing(false);
|
|
34
|
+
console.debug(`[useImageProcessor] Cancelled processing for image ${photoId}`);
|
|
35
|
+
};
|
|
24
36
|
// Memoize adjustments to prevent unnecessary effect triggers
|
|
25
37
|
const adjustmentsString = useMemo(() => adjustments ? JSON.stringify(adjustments) : '', [adjustments]);
|
|
26
38
|
const frameMemoized = useMemo(() => frame, [frame]);
|
|
@@ -69,8 +81,21 @@ export function useImageProcessor({ photoId, photoSrc, enableEditor = true, adju
|
|
|
69
81
|
cancelled = true;
|
|
70
82
|
};
|
|
71
83
|
}, [photoSrc, adjustmentsString, frameMemoized, enableEditor, isEditorReady, processImage, photoId]);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (!abortSignal)
|
|
86
|
+
return;
|
|
87
|
+
const handleAbort = () => {
|
|
88
|
+
cancelProcessing();
|
|
89
|
+
};
|
|
90
|
+
abortSignal.addEventListener('abort', handleAbort);
|
|
91
|
+
return () => {
|
|
92
|
+
abortSignal.removeEventListener('abort', handleAbort);
|
|
93
|
+
};
|
|
94
|
+
}, [abortSignal]);
|
|
72
95
|
return {
|
|
73
96
|
processedImageSrc,
|
|
74
|
-
isProcessingComplete
|
|
97
|
+
isProcessingComplete,
|
|
98
|
+
cancelProcessing,
|
|
99
|
+
isProcessing
|
|
75
100
|
};
|
|
76
101
|
}
|
package/dist/services/type.d.ts
CHANGED
package/package.json
CHANGED
package/dist/services/base.d.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
|
|
2
|
-
import { Observable } from "rxjs/internal/Observable";
|
|
3
|
-
export declare const api: any;
|
|
4
|
-
export interface ResponseData<T> {
|
|
5
|
-
code?: number;
|
|
6
|
-
message?: string;
|
|
7
|
-
data?: T;
|
|
8
|
-
error_message?: string;
|
|
9
|
-
}
|
|
10
|
-
export declare class ResponseError extends Error {
|
|
11
|
-
code: number;
|
|
12
|
-
error_message: string;
|
|
13
|
-
isEmptyData: boolean;
|
|
14
|
-
constructor(code: number, error_message: string, originalError?: Error, isEmptyData?: boolean);
|
|
15
|
-
}
|
|
16
|
-
export declare class EmptyDataError extends Error {
|
|
17
|
-
constructor();
|
|
18
|
-
}
|
|
19
|
-
export declare function handleResponse<T>(res: AxiosResponse<ResponseData<T>>): T;
|
|
20
|
-
export declare function handleError(error: any): Observable<any>;
|
|
21
|
-
export declare function isResponseError(error: any): Boolean;
|
|
22
|
-
/**
|
|
23
|
-
* @deprecated use axiosGetObservable, axiosPostObservable, axiosPutObservable, axiosDeleteObservable instead
|
|
24
|
-
* @param promise
|
|
25
|
-
*/
|
|
26
|
-
export declare function fromAxiosToObservable<T>(promise: Promise<AxiosResponse<ResponseData<T>>>): Observable<T>;
|
|
27
|
-
export declare const apiV3: any;
|
|
28
|
-
export declare class BaseServices {
|
|
29
|
-
protected axios: AxiosInstance;
|
|
30
|
-
protected constructor(axios: AxiosInstance);
|
|
31
|
-
protected axiosGetObservable<T>(url: string, params?: AxiosRequestConfig<any> | undefined): Observable<T>;
|
|
32
|
-
protected axiosPostObservable<T>(url: string, data: any, params?: AxiosRequestConfig<any> | undefined): Observable<T>;
|
|
33
|
-
protected axiosPutObservable<T>(url: string, data: any, params?: AxiosRequestConfig<any> | undefined): Observable<T>;
|
|
34
|
-
protected axiosDeleteObservable<T>(url: string, params?: AxiosRequestConfig<any> | undefined): Observable<T>;
|
|
35
|
-
}
|
|
36
|
-
export interface Result<T> {
|
|
37
|
-
getStatus(): "loading" | "success" | "error" | "not-found" | "idle";
|
|
38
|
-
getData(): T;
|
|
39
|
-
getDataOrNull(): T | null | undefined;
|
|
40
|
-
getError(): any;
|
|
41
|
-
}
|
|
42
|
-
export declare class ResultImpl<T> implements Result<T> {
|
|
43
|
-
private readonly status;
|
|
44
|
-
private readonly data;
|
|
45
|
-
private readonly error;
|
|
46
|
-
getStatus(): "loading" | "success" | "error" | "not-found" | "idle";
|
|
47
|
-
getData(): T;
|
|
48
|
-
getError(): any;
|
|
49
|
-
getDataOrNull(): T | null | undefined;
|
|
50
|
-
private constructor();
|
|
51
|
-
static success<T>(data: T): Result<T>;
|
|
52
|
-
static loading<T>(): Result<T>;
|
|
53
|
-
static error<T>(err: any): Result<T>;
|
|
54
|
-
static notFound<T>(): Result<T>;
|
|
55
|
-
static idle<T>(): Result<T>;
|
|
56
|
-
}
|
|
57
|
-
export declare function fromPromise<T>(promise: Promise<T>): Observable<T>;
|
package/dist/services/base.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import axiosRetry from 'axios-retry';
|
|
3
|
-
import { Observable } from "rxjs/internal/Observable";
|
|
4
|
-
import { catchError, from, map } from "rxjs";
|
|
5
|
-
const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:8080";
|
|
6
|
-
const apiConfig = (version) => {
|
|
7
|
-
return axios.create({
|
|
8
|
-
baseURL: `${BASE_URL}/${version}/`,
|
|
9
|
-
timeout: 60000 * 2,
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
export const api = axios.create({
|
|
13
|
-
baseURL: `${BASE_URL}`,
|
|
14
|
-
timeout: 60000 * 2,
|
|
15
|
-
});
|
|
16
|
-
axiosRetry(api, { retries: 3, retryDelay: axiosRetry.linearDelay() });
|
|
17
|
-
export class ResponseError extends Error {
|
|
18
|
-
constructor(code, error_message, originalError, isEmptyData = false) {
|
|
19
|
-
super(`${code}: ${error_message}`);
|
|
20
|
-
this.isEmptyData = false;
|
|
21
|
-
this.code = code;
|
|
22
|
-
this.error_message = error_message;
|
|
23
|
-
this.isEmptyData = isEmptyData;
|
|
24
|
-
if (originalError && originalError.stack) {
|
|
25
|
-
this.stack += `\nCaused by: ${originalError.stack}`;
|
|
26
|
-
}
|
|
27
|
-
// we need to set prototype to make this object can check by
|
|
28
|
-
// instanceof ResponseError
|
|
29
|
-
Object.setPrototypeOf(this, ResponseError.prototype);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
export class EmptyDataError extends Error {
|
|
33
|
-
constructor() {
|
|
34
|
-
super("Data Empty, server not send any data in response");
|
|
35
|
-
// we need to set prototype to make this object can check by
|
|
36
|
-
// instanceof EmptyDataError
|
|
37
|
-
Object.setPrototypeOf(this, EmptyDataError.prototype);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
// get data from response
|
|
41
|
-
export function handleResponse(res) {
|
|
42
|
-
if (!res.data.data) {
|
|
43
|
-
throw new EmptyDataError();
|
|
44
|
-
}
|
|
45
|
-
return res.data.data;
|
|
46
|
-
}
|
|
47
|
-
function mapError(error) {
|
|
48
|
-
if (error.isAxiosError) {
|
|
49
|
-
if (error.response) {
|
|
50
|
-
if (typeof error.response.data === "string") {
|
|
51
|
-
return {
|
|
52
|
-
code: error.response.status,
|
|
53
|
-
message: `${error.response.status}: ${error.response.statusText}`,
|
|
54
|
-
data: undefined,
|
|
55
|
-
error_message: error.response.data,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
return error.response?.data;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
else if (error.request) {
|
|
63
|
-
return {
|
|
64
|
-
code: 400,
|
|
65
|
-
message: "`${error.name}: failed connect to server check your connection`",
|
|
66
|
-
data: undefined,
|
|
67
|
-
error_message: "failed connect to server",
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
return {
|
|
72
|
-
code: 400,
|
|
73
|
-
message: error.message,
|
|
74
|
-
data: undefined,
|
|
75
|
-
error_message: error.message,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
return {
|
|
81
|
-
code: 500,
|
|
82
|
-
message: String(error),
|
|
83
|
-
data: undefined,
|
|
84
|
-
error_message: String(error),
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
// handle error from response convert it and throw it as ResponseError
|
|
89
|
-
export function handleError(error) {
|
|
90
|
-
if (error instanceof EmptyDataError) {
|
|
91
|
-
// if data is empty just throw error
|
|
92
|
-
throw new ResponseError(204, "Data Empty, server not send any data in response", error, true);
|
|
93
|
-
}
|
|
94
|
-
let response = mapError(error);
|
|
95
|
-
throw new ResponseError(response.code || 500, response.error_message || "Unknown error", error);
|
|
96
|
-
}
|
|
97
|
-
export function isResponseError(error) {
|
|
98
|
-
return !!((error.code) && (error.error_message));
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* @deprecated use axiosGetObservable, axiosPostObservable, axiosPutObservable, axiosDeleteObservable instead
|
|
102
|
-
* @param promise
|
|
103
|
-
*/
|
|
104
|
-
export function fromAxiosToObservable(promise) {
|
|
105
|
-
return from(promise).pipe(map(handleResponse), catchError(handleError));
|
|
106
|
-
}
|
|
107
|
-
export const apiV3 = apiConfig('v3');
|
|
108
|
-
export class BaseServices {
|
|
109
|
-
constructor(axios) {
|
|
110
|
-
this.axios = axios;
|
|
111
|
-
}
|
|
112
|
-
axiosGetObservable(url, params) {
|
|
113
|
-
return new Observable(subscriber => {
|
|
114
|
-
const controller = new AbortController();
|
|
115
|
-
const paramsData = { signal: controller.signal, ...params };
|
|
116
|
-
this.axios.get(url, paramsData)
|
|
117
|
-
.then(res => {
|
|
118
|
-
console.debug({ res, url, params }, "success GET request");
|
|
119
|
-
subscriber.next(res);
|
|
120
|
-
subscriber.complete();
|
|
121
|
-
})
|
|
122
|
-
.catch((error) => {
|
|
123
|
-
console.error({ error, url, params }, "Failed GET request");
|
|
124
|
-
subscriber.error(error);
|
|
125
|
-
});
|
|
126
|
-
return () => {
|
|
127
|
-
console.debug({ url, params, method: "GET" }, "Abort request");
|
|
128
|
-
controller.abort();
|
|
129
|
-
};
|
|
130
|
-
}).pipe(map(handleResponse), catchError(handleError));
|
|
131
|
-
}
|
|
132
|
-
axiosPostObservable(url, data, params) {
|
|
133
|
-
return new Observable(subscriber => {
|
|
134
|
-
const controller = new AbortController();
|
|
135
|
-
const paramsData = { signal: controller.signal, ...params };
|
|
136
|
-
this.axios.post(url, data, paramsData)
|
|
137
|
-
.then(res => {
|
|
138
|
-
console.debug({ res, url, params }, "success POST request");
|
|
139
|
-
subscriber.next(res);
|
|
140
|
-
subscriber.complete();
|
|
141
|
-
})
|
|
142
|
-
.catch((error) => {
|
|
143
|
-
console.error({ error, url, params }, "Failed POST request");
|
|
144
|
-
subscriber.error(error);
|
|
145
|
-
});
|
|
146
|
-
return () => {
|
|
147
|
-
console.debug({ url, params, method: "POST" }, "Abort request");
|
|
148
|
-
controller.abort();
|
|
149
|
-
};
|
|
150
|
-
}).pipe(map(handleResponse), catchError(handleError));
|
|
151
|
-
}
|
|
152
|
-
axiosPutObservable(url, data, params) {
|
|
153
|
-
return new Observable(subscriber => {
|
|
154
|
-
const controller = new AbortController();
|
|
155
|
-
const paramsData = { signal: controller.signal, ...params };
|
|
156
|
-
this.axios.put(url, data, paramsData)
|
|
157
|
-
.then(res => {
|
|
158
|
-
console.debug({ res, url, params }, "success PUT request");
|
|
159
|
-
subscriber.next(res);
|
|
160
|
-
subscriber.complete();
|
|
161
|
-
})
|
|
162
|
-
.catch((error) => {
|
|
163
|
-
console.error({ error, url, params }, "Failed PUT request");
|
|
164
|
-
subscriber.error(error);
|
|
165
|
-
});
|
|
166
|
-
return () => {
|
|
167
|
-
console.debug({ url, params, method: "PUT" }, "Abort request");
|
|
168
|
-
controller.abort();
|
|
169
|
-
};
|
|
170
|
-
}).pipe(map(handleResponse), catchError(handleError));
|
|
171
|
-
}
|
|
172
|
-
axiosDeleteObservable(url, params) {
|
|
173
|
-
return new Observable(subscriber => {
|
|
174
|
-
const controller = new AbortController();
|
|
175
|
-
const paramsData = { signal: controller.signal, ...params };
|
|
176
|
-
this.axios.delete(url, paramsData)
|
|
177
|
-
.then(res => {
|
|
178
|
-
console.debug({ res, url, params }, "success DELETE request");
|
|
179
|
-
subscriber.next(res);
|
|
180
|
-
subscriber.complete();
|
|
181
|
-
})
|
|
182
|
-
.catch((error) => {
|
|
183
|
-
console.error({ error, url, params }, "Failed DELETE request");
|
|
184
|
-
subscriber.error(error);
|
|
185
|
-
});
|
|
186
|
-
return () => {
|
|
187
|
-
console.debug({ url, params, method: "DELETE" }, "Abort request");
|
|
188
|
-
controller.abort();
|
|
189
|
-
};
|
|
190
|
-
}).pipe(map(handleResponse), catchError(handleError));
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
export class ResultImpl {
|
|
194
|
-
getStatus() {
|
|
195
|
-
return this.status;
|
|
196
|
-
}
|
|
197
|
-
getData() {
|
|
198
|
-
if (this.data)
|
|
199
|
-
return this.data;
|
|
200
|
-
throw new Error("Data is not available");
|
|
201
|
-
}
|
|
202
|
-
getError() {
|
|
203
|
-
if (this.error)
|
|
204
|
-
return this.error;
|
|
205
|
-
throw new Error("Error is not available");
|
|
206
|
-
}
|
|
207
|
-
getDataOrNull() {
|
|
208
|
-
return this.data;
|
|
209
|
-
}
|
|
210
|
-
constructor(status, data, error) {
|
|
211
|
-
this.status = "idle";
|
|
212
|
-
this.status = status;
|
|
213
|
-
this.data = data;
|
|
214
|
-
this.error = error;
|
|
215
|
-
}
|
|
216
|
-
static success(data) {
|
|
217
|
-
return new ResultImpl("success", data, null);
|
|
218
|
-
}
|
|
219
|
-
static loading() {
|
|
220
|
-
return new ResultImpl("loading");
|
|
221
|
-
}
|
|
222
|
-
static error(err) {
|
|
223
|
-
return new ResultImpl("error", null, err);
|
|
224
|
-
}
|
|
225
|
-
static notFound() {
|
|
226
|
-
return new ResultImpl("not-found");
|
|
227
|
-
}
|
|
228
|
-
static idle() {
|
|
229
|
-
return new ResultImpl("idle");
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
export function fromPromise(promise) {
|
|
233
|
-
return new Observable(subscriber => {
|
|
234
|
-
promise.then(value => {
|
|
235
|
-
console.debug({ value }, "Promise success");
|
|
236
|
-
subscriber.next(value);
|
|
237
|
-
subscriber.complete();
|
|
238
|
-
}).catch(err => {
|
|
239
|
-
console.error({ err }, "Promise error");
|
|
240
|
-
subscriber.error(err);
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
}
|