@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.
@@ -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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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), onMouseDown: () => {
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,2 @@
1
+ import React from "react";
2
+ export default function useSliderEvents(onDragStart: () => void, onDragEnd: () => void, isBatchMode: boolean): React.RefObject<HTMLDivElement>;
@@ -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
- // export { HonchoEditorBulkDemo } from './hooks/demo/HonchoEditorBulkDemo';
3
- // export { HonchoEditorSingleCleanDemo } from './hooks/demo/HonchoEditorSingleCleanDemo';
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,4 +1,4 @@
1
- import type { EditorTask, EditorResponse } from '../lib/context/EditorProcessingService';
1
+ import type { EditorTask, EditorResponse } from '../../lib/context/EditorProcessingService';
2
2
  interface UseEditorOptions {
3
3
  priority?: number;
4
4
  }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { useCallback } from 'react';
3
- import { useEditorContext } from '../lib/context/EditorContext';
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 '../lib/editor/honcho-editor';
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: any;
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 '../utils/imageLoader';
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 '../lib/editor/honcho-editor';
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 '../lib/hooks/useEditor';
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
  }
@@ -1,4 +1,10 @@
1
- import { Content } from "@/types";
1
+ export interface Content {
2
+ key: string;
3
+ path: string;
4
+ size: number;
5
+ width: number;
6
+ height: number;
7
+ }
2
8
  export interface Response<T> {
3
9
  code: number;
4
10
  data?: T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yogiswara/honcho-editor-ui",
3
- "version": "2.10.0",
3
+ "version": "2.10.2",
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",
@@ -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>;
@@ -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
- }