@yogiswara/honcho-editor-ui 3.1.9 → 3.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,81 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
2
3
  import { Stack, Slider, Typography } from "@mui/material";
3
4
  import useHonchoTypography from "../../themes/honchoTheme";
4
5
  import useColors from '../../themes/colors';
5
6
  import useSliderEvents from "../editor/sliderComponents/useSliderEvents";
7
+ const formatValue = (value) => {
8
+ if (value > 0)
9
+ return `+${value}`;
10
+ if (value < 0)
11
+ return value.toString();
12
+ return "0";
13
+ };
14
+ function useAdjustmentField(propValue, setValue, onDragStart, onDragEnd, isBatchMode) {
15
+ const [local, setLocal] = useState(formatValue(propValue));
16
+ const [started, setStarted] = useState(false);
17
+ // keep sync with external changes
18
+ useEffect(() => {
19
+ setLocal(formatValue(propValue));
20
+ }, [propValue]);
21
+ const handleChange = (e, min, max) => {
22
+ const raw = e.target.value;
23
+ setLocal(raw);
24
+ if (raw === "" || raw === "+" || raw === "-")
25
+ return;
26
+ let num = parseInt(raw, 10);
27
+ if (isNaN(num))
28
+ return;
29
+ num = Math.max(min, Math.min(max, num));
30
+ // start batch on first valid change
31
+ if (!started && !isBatchMode) {
32
+ onDragStart();
33
+ console.log("[MOBILE UI] Starting batch: ", onDragStart);
34
+ setStarted(true);
35
+ }
36
+ setValue(num);
37
+ };
38
+ const handleDoubleClick = () => {
39
+ if (!isBatchMode) {
40
+ onDragStart();
41
+ }
42
+ setLocal("0");
43
+ setValue(0);
44
+ if (!isBatchMode) {
45
+ console.log("[MOBILE UI] ending batch: ", onDragEnd);
46
+ onDragEnd();
47
+ }
48
+ };
49
+ const handleBlur = (min, max) => {
50
+ if (local === "" || local === "+" || local === "-") {
51
+ setLocal("0");
52
+ setValue(0);
53
+ }
54
+ else {
55
+ let num = parseInt(local, 10);
56
+ if (isNaN(num))
57
+ num = 0;
58
+ num = Math.max(min, Math.min(max, num));
59
+ setLocal(formatValue(num));
60
+ setValue(num);
61
+ }
62
+ // end batch when user leaves field
63
+ if (started) {
64
+ onDragEnd();
65
+ setStarted(false);
66
+ }
67
+ };
68
+ const handleKeyDown = (e) => {
69
+ if (e.key === "Enter") {
70
+ e.target.blur(); // blur the actual input
71
+ if (started) {
72
+ onDragEnd();
73
+ setStarted(false);
74
+ }
75
+ }
76
+ };
77
+ return { local, handleChange, handleBlur, handleKeyDown, handleDoubleClick };
78
+ }
6
79
  export default function HSliderLightMobile(props) {
7
80
  const typography = useHonchoTypography();
8
81
  const colors = useColors();
@@ -12,22 +85,13 @@ export default function HSliderLightMobile(props) {
12
85
  const shadowsSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
13
86
  const whitesSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
14
87
  const blacksSliderRef = useSliderEvents(props.onDragStart, props.onDragEnd, props.isBatchMode);
15
- const formatValue = (value) => {
16
- if (value > 0)
17
- return `+${value}`;
18
- return value.toString();
19
- };
20
- const handleInputChange = (event, min, max, onChange) => {
21
- const value = event.target.value;
22
- if (value === '+' || value === '-')
23
- return;
24
- let numericValue = parseInt(value, 10);
25
- if (isNaN(numericValue))
26
- numericValue = 0;
27
- const clampedValue = Math.max(min, Math.min(max, numericValue));
28
- onChange(clampedValue);
29
- };
30
- return (_jsx(_Fragment, { children: _jsxs(Stack, { spacing: 0, direction: "column", sx: { width: '100%', paddingX: 1 }, children: [_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, userSelect: 'none' }, onDoubleClick: () => props.onExposureChange("exposureScore", 0), children: "Exposure" }), _jsx(Typography, { sx: {
88
+ const exposureInput = useAdjustmentField(props.exposureScore, (val) => props.onExposureChange("exposureScore", val), props.onDragStart, props.onDragEnd, props.isBatchMode);
89
+ const contrastInput = useAdjustmentField(props.contrastScore, (val) => props.onExposureChange("contrastScore", val), props.onDragStart, props.onDragEnd, props.isBatchMode);
90
+ const highlightsInput = useAdjustmentField(props.highlightsScore, (val) => props.onHighlightsChange("highlightsScore", val), props.onDragStart, props.onDragEnd, props.isBatchMode);
91
+ const shadowsInput = useAdjustmentField(props.shadowScore, (val) => props.onShadowsChange("shadowsScore", val), props.onDragStart, props.onDragEnd, props.isBatchMode);
92
+ const whitesInput = useAdjustmentField(props.whiteScore, (val) => props.onWhitesChange("whitesScore", val), props.onDragStart, props.onDragEnd, props.isBatchMode);
93
+ const blacksInput = useAdjustmentField(props.blackScore, (val) => props.onBlacksChange("blacksScore", val), props.onDragStart, props.onDragEnd, props.isBatchMode);
94
+ return (_jsx(_Fragment, { children: _jsxs(Stack, { spacing: 0, direction: "column", sx: { width: '100%', paddingX: 1 }, children: [_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, userSelect: 'none' }, onDoubleClick: exposureInput.handleDoubleClick, children: "Exposure" }), _jsx(Typography, { sx: {
31
95
  ...typography.bodyMedium, // Use your standard typography
32
96
  color: colors.surface,
33
97
  width: "40px", // Keep the fixed width for alignment
@@ -53,7 +117,7 @@ export default function HSliderLightMobile(props) {
53
117
  thumb: {
54
118
  ref: exposureSliderRef
55
119
  }
56
- }, 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, userSelect: 'none' }, children: "Contrast" }), _jsx(Typography, { sx: {
120
+ }, size: "small", value: props.exposureScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onExposureChange("exposureScore", newValue), onDoubleClick: exposureInput.handleDoubleClick }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, userSelect: 'none' }, onDoubleClick: contrastInput.handleDoubleClick, children: "Contrast" }), _jsx(Typography, { sx: {
57
121
  ...typography.bodyMedium, // Use your standard typography
58
122
  color: colors.surface,
59
123
  width: "40px", // Keep the fixed width for alignment
@@ -80,7 +144,7 @@ export default function HSliderLightMobile(props) {
80
144
  thumb: {
81
145
  ref: contrastSliderRef
82
146
  }
83
- }, 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(Typography, { sx: {
147
+ }, size: "small", value: props.contrastScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onContrastChange("contrastScore", newValue), onDoubleClick: contrastInput.handleDoubleClick }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, userSelect: 'none' }, onDoubleClick: highlightsInput.handleDoubleClick, children: "Highlights" }), _jsx(Typography, { sx: {
84
148
  ...typography.bodyMedium, // Use your standard typography
85
149
  color: colors.surface,
86
150
  width: "40px", // Keep the fixed width for alignment
@@ -107,7 +171,7 @@ export default function HSliderLightMobile(props) {
107
171
  thumb: {
108
172
  ref: highlightsSliderRef
109
173
  }
110
- }, 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(Typography, { sx: {
174
+ }, size: "small", value: props.highlightsScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onHighlightsChange("highlightsScore", newValue), onDoubleClick: highlightsInput.handleDoubleClick }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, userSelect: 'none' }, onDoubleClick: shadowsInput.handleDoubleClick, children: "Shadows" }), _jsx(Typography, { sx: {
111
175
  ...typography.bodyMedium, // Use your standard typography
112
176
  color: colors.surface,
113
177
  width: "40px", // Keep the fixed width for alignment
@@ -134,7 +198,7 @@ export default function HSliderLightMobile(props) {
134
198
  thumb: {
135
199
  ref: shadowsSliderRef
136
200
  }
137
- }, 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(Typography, { sx: {
201
+ }, size: "small", value: props.shadowScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onShadowsChange("shadowsScore", newValue), onDoubleClick: shadowsInput.handleDoubleClick }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, userSelect: 'none' }, onDoubleClick: whitesInput.handleDoubleClick, children: "Whites" }), _jsx(Typography, { sx: {
138
202
  ...typography.bodyMedium, // Use your standard typography
139
203
  color: colors.surface,
140
204
  width: "40px", // Keep the fixed width for alignment
@@ -161,7 +225,7 @@ export default function HSliderLightMobile(props) {
161
225
  thumb: {
162
226
  ref: whitesSliderRef
163
227
  }
164
- }, 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(Typography, { sx: {
228
+ }, size: "small", value: props.whiteScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onWhitesChange("whitesScore", newValue), onDoubleClick: whitesInput.handleDoubleClick }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { pt: '10px', pb: '0px' }, children: [_jsx(Typography, { sx: { ...typography.bodyMedium, color: colors.surface, userSelect: 'none' }, onDoubleClick: blacksInput.handleDoubleClick, children: "Blacks" }), _jsx(Typography, { sx: {
165
229
  ...typography.bodyMedium, // Use your standard typography
166
230
  color: colors.surface,
167
231
  width: "40px", // Keep the fixed width for alignment
@@ -188,5 +252,5 @@ export default function HSliderLightMobile(props) {
188
252
  thumb: {
189
253
  ref: blacksSliderRef
190
254
  }
191
- }, size: "small", value: props.blackScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onBlacksChange("blacksScore", newValue), onDoubleClick: () => props.onBlacksChange("blacksScore", 0) })] }) }));
255
+ }, size: "small", value: props.blackScore, step: 1, min: -100, max: 100, onChange: (_event, newValue) => props.onBlacksChange("blacksScore", newValue), onDoubleClick: blacksInput.handleDoubleClick })] }) }));
192
256
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yogiswara/honcho-editor-ui",
3
- "version": "3.1.9",
3
+ "version": "3.1.10",
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",