@pie-lib/config-ui 12.0.0-beta.4 → 12.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +8 -1653
- package/CHANGELOG.md +540 -58
- package/LICENSE.md +5 -0
- package/NEXT.CHANGELOG.json +1 -0
- package/lib/alert-dialog.js +44 -20
- package/lib/alert-dialog.js.map +1 -1
- package/lib/checkbox.js +59 -61
- package/lib/checkbox.js.map +1 -1
- package/lib/choice-configuration/feedback-menu.js +30 -65
- package/lib/choice-configuration/feedback-menu.js.map +1 -1
- package/lib/choice-configuration/index.js +231 -244
- package/lib/choice-configuration/index.js.map +1 -1
- package/lib/choice-utils.js +7 -19
- package/lib/choice-utils.js.map +1 -1
- package/lib/feedback-config/feedback-selector.js +89 -115
- package/lib/feedback-config/feedback-selector.js.map +1 -1
- package/lib/feedback-config/group.js +28 -42
- package/lib/feedback-config/group.js.map +1 -1
- package/lib/feedback-config/index.js +55 -87
- package/lib/feedback-config/index.js.map +1 -1
- package/lib/form-section.js +32 -34
- package/lib/form-section.js.map +1 -1
- package/lib/help.js +41 -80
- package/lib/help.js.map +1 -1
- package/lib/index.js +2 -32
- package/lib/index.js.map +1 -1
- package/lib/input.js +24 -57
- package/lib/input.js.map +1 -1
- package/lib/inputs.js +62 -88
- package/lib/inputs.js.map +1 -1
- package/lib/langs.js +59 -102
- package/lib/langs.js.map +1 -1
- package/lib/layout/config-layout.js +95 -67
- package/lib/layout/config-layout.js.map +1 -1
- package/lib/layout/index.js +1 -4
- package/lib/layout/index.js.map +1 -1
- package/lib/layout/layout-contents.js +130 -75
- package/lib/layout/layout-contents.js.map +1 -1
- package/lib/layout/settings-box.js +28 -58
- package/lib/layout/settings-box.js.map +1 -1
- package/lib/mui-box/index.js +42 -58
- package/lib/mui-box/index.js.map +1 -1
- package/lib/number-text-field-custom.js +164 -152
- package/lib/number-text-field-custom.js.map +1 -1
- package/lib/number-text-field.js +87 -119
- package/lib/number-text-field.js.map +1 -1
- package/lib/radio-with-label.js +33 -26
- package/lib/radio-with-label.js.map +1 -1
- package/lib/settings/display-size.js +17 -33
- package/lib/settings/display-size.js.map +1 -1
- package/lib/settings/index.js +26 -46
- package/lib/settings/index.js.map +1 -1
- package/lib/settings/panel.js +202 -221
- package/lib/settings/panel.js.map +1 -1
- package/lib/settings/settings-radio-label.js +37 -29
- package/lib/settings/settings-radio-label.js.map +1 -1
- package/lib/settings/toggle.js +40 -33
- package/lib/settings/toggle.js.map +1 -1
- package/lib/tabs/index.js +26 -57
- package/lib/tabs/index.js.map +1 -1
- package/lib/tags-input/index.js +51 -100
- package/lib/tags-input/index.js.map +1 -1
- package/lib/two-choice.js +47 -91
- package/lib/two-choice.js.map +1 -1
- package/lib/with-stateful-model.js +11 -34
- package/lib/with-stateful-model.js.map +1 -1
- package/package.json +22 -11
- package/src/__tests__/alert-dialog.test.jsx +283 -0
- package/src/__tests__/checkbox.test.jsx +249 -0
- package/src/__tests__/choice-utils.test.js +12 -0
- package/src/__tests__/form-section.test.jsx +334 -0
- package/src/__tests__/help.test.jsx +184 -0
- package/src/__tests__/input.test.jsx +192 -0
- package/src/__tests__/langs.test.jsx +457 -0
- package/src/__tests__/number-text-field-custom.test.jsx +438 -0
- package/src/__tests__/number-text-field.test.jsx +341 -0
- package/src/__tests__/radio-with-label.test.jsx +259 -0
- package/src/__tests__/settings-panel.test.js +187 -0
- package/src/__tests__/settings.test.jsx +515 -0
- package/src/__tests__/tabs.test.jsx +193 -0
- package/src/__tests__/two-choice.test.js +110 -0
- package/src/__tests__/with-stateful-model.test.jsx +145 -0
- package/src/alert-dialog.jsx +31 -16
- package/src/checkbox.jsx +45 -39
- package/src/choice-configuration/__tests__/feedback-menu.test.jsx +163 -0
- package/src/choice-configuration/__tests__/index.test.jsx +234 -0
- package/src/choice-configuration/feedback-menu.jsx +15 -28
- package/src/choice-configuration/index.jsx +233 -182
- package/src/choice-utils.js +1 -1
- package/src/feedback-config/__tests__/feedback-config.test.jsx +141 -0
- package/src/feedback-config/__tests__/feedback-selector.test.jsx +107 -0
- package/src/feedback-config/feedback-selector.jsx +65 -60
- package/src/feedback-config/group.jsx +26 -29
- package/src/feedback-config/index.jsx +59 -47
- package/src/form-section.jsx +26 -18
- package/src/help.jsx +27 -36
- package/src/index.js +2 -5
- package/src/input.jsx +9 -9
- package/src/inputs.jsx +36 -50
- package/src/langs.jsx +57 -73
- package/src/layout/__tests__/config.layout.test.jsx +59 -0
- package/src/layout/__tests__/layout-content.test.jsx +3 -0
- package/src/layout/config-layout.jsx +70 -37
- package/src/layout/layout-contents.jsx +96 -39
- package/src/layout/settings-box.jsx +22 -21
- package/src/mui-box/index.jsx +37 -45
- package/src/number-text-field-custom.jsx +136 -81
- package/src/number-text-field.jsx +59 -37
- package/src/radio-with-label.jsx +28 -12
- package/src/settings/display-size.jsx +14 -13
- package/src/settings/index.js +20 -12
- package/src/settings/panel.jsx +147 -110
- package/src/settings/settings-radio-label.jsx +29 -13
- package/src/settings/toggle.jsx +39 -20
- package/src/tabs/index.jsx +15 -19
- package/src/tags-input/__tests__/index.test.jsx +113 -0
- package/src/tags-input/index.jsx +42 -47
- package/src/two-choice.jsx +19 -23
- package/src/with-stateful-model.jsx +5 -5
- package/README.md +0 -12
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import TextField from '@material
|
|
4
|
-
import
|
|
5
|
-
import { withStyles } from '@material-ui/core/styles';
|
|
3
|
+
import TextField from '@mui/material/TextField';
|
|
4
|
+
import { styled } from '@mui/material/styles';
|
|
6
5
|
import isFinite from 'lodash/isFinite';
|
|
7
|
-
import IconButton from '@material
|
|
8
|
-
import InputAdornment from '@material
|
|
9
|
-
import Remove from '@
|
|
10
|
-
import Add from '@
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
'& input[type=number]::-webkit-outer-spin-button': {
|
|
18
|
-
'-webkit-appearance': 'none',
|
|
19
|
-
margin: 0
|
|
20
|
-
},
|
|
21
|
-
'& input[type=number]::-webkit-inner-spin-button': {
|
|
22
|
-
'-webkit-appearance': 'none',
|
|
23
|
-
margin: 0
|
|
24
|
-
}
|
|
6
|
+
import IconButton from '@mui/material/IconButton';
|
|
7
|
+
import InputAdornment from '@mui/material/InputAdornment';
|
|
8
|
+
import Remove from '@mui/icons-material/Remove';
|
|
9
|
+
import Add from '@mui/icons-material/Add';
|
|
10
|
+
import * as math from 'mathjs';
|
|
11
|
+
|
|
12
|
+
const StyledTextField = styled(TextField)(() => ({
|
|
13
|
+
'& input[type=number]': {
|
|
14
|
+
MozAppearance: 'textfield',
|
|
25
15
|
},
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
16
|
+
'& input[type=number]::-webkit-outer-spin-button': {
|
|
17
|
+
WebkitAppearance: 'none',
|
|
18
|
+
margin: 0,
|
|
19
|
+
},
|
|
20
|
+
'& input[type=number]::-webkit-inner-spin-button': {
|
|
21
|
+
WebkitAppearance: 'none',
|
|
22
|
+
margin: 0,
|
|
23
|
+
},
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
const StyledIconButton = styled(IconButton)(() => ({
|
|
27
|
+
padding: '2px',
|
|
28
|
+
}));
|
|
30
29
|
|
|
31
30
|
const fallbackNumber = (min, max) => {
|
|
32
31
|
if (!isFinite(min) && !isFinite(max)) {
|
|
@@ -44,21 +43,23 @@ const fallbackNumber = (min, max) => {
|
|
|
44
43
|
|
|
45
44
|
export class NumberTextFieldCustom extends React.Component {
|
|
46
45
|
static propTypes = {
|
|
47
|
-
classes: PropTypes.object.isRequired,
|
|
48
46
|
className: PropTypes.string,
|
|
49
47
|
customValues: PropTypes.array,
|
|
50
48
|
disabled: PropTypes.bool,
|
|
51
49
|
error: PropTypes.bool,
|
|
52
50
|
inputClassName: PropTypes.string,
|
|
51
|
+
helperText: PropTypes.string,
|
|
53
52
|
onChange: PropTypes.func.isRequired,
|
|
54
53
|
onlyIntegersAllowed: PropTypes.bool,
|
|
55
|
-
value: PropTypes.
|
|
54
|
+
value: PropTypes.any,
|
|
56
55
|
min: PropTypes.number,
|
|
57
56
|
max: PropTypes.number,
|
|
58
57
|
step: PropTypes.number,
|
|
59
58
|
label: PropTypes.string,
|
|
60
59
|
disableUnderline: PropTypes.bool,
|
|
61
|
-
|
|
60
|
+
textAlign: PropTypes.string,
|
|
61
|
+
variant: PropTypes.string,
|
|
62
|
+
type: PropTypes.string,
|
|
62
63
|
};
|
|
63
64
|
|
|
64
65
|
static defaultProps = {
|
|
@@ -66,7 +67,7 @@ export class NumberTextFieldCustom extends React.Component {
|
|
|
66
67
|
customValues: [],
|
|
67
68
|
textAlign: 'center',
|
|
68
69
|
variant: 'standard',
|
|
69
|
-
onlyIntegersAllowed: false
|
|
70
|
+
onlyIntegersAllowed: false,
|
|
70
71
|
};
|
|
71
72
|
|
|
72
73
|
constructor(props) {
|
|
@@ -76,7 +77,7 @@ export class NumberTextFieldCustom extends React.Component {
|
|
|
76
77
|
|
|
77
78
|
this.state = {
|
|
78
79
|
value,
|
|
79
|
-
currentIndex
|
|
80
|
+
currentIndex,
|
|
80
81
|
};
|
|
81
82
|
|
|
82
83
|
if (value !== props.value) {
|
|
@@ -87,13 +88,13 @@ export class NumberTextFieldCustom extends React.Component {
|
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
UNSAFE_componentWillReceiveProps(props) {
|
|
90
|
-
const { value, currentIndex } = this.normalizeValueAndIndex(props.customValues, props.value);
|
|
91
|
+
const { value, currentIndex } = this.normalizeValueAndIndex(props.customValues, props.value, props.min, props.max);
|
|
91
92
|
|
|
92
93
|
this.setState({ value, currentIndex });
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
clamp(value) {
|
|
96
|
-
const {
|
|
96
|
+
clamp(value, min = this.props.min, max = this.props.max) {
|
|
97
|
+
const { customValues } = this.props;
|
|
97
98
|
|
|
98
99
|
if ((customValues || []).length > 0) {
|
|
99
100
|
return value;
|
|
@@ -114,12 +115,14 @@ export class NumberTextFieldCustom extends React.Component {
|
|
|
114
115
|
return value;
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
normalizeValueAndIndex = (customValues, number) => {
|
|
118
|
-
const
|
|
119
|
-
const
|
|
118
|
+
normalizeValueAndIndex = (customValues, number, min, max) => {
|
|
119
|
+
const { type } = this.props;
|
|
120
|
+
const value = this.clamp(number, min, max);
|
|
121
|
+
const currentIndex = (customValues || []).findIndex((val) => val === value);
|
|
120
122
|
|
|
121
123
|
if ((customValues || []).length > 0 && currentIndex === -1) {
|
|
122
|
-
const closestValue =
|
|
124
|
+
const closestValue =
|
|
125
|
+
type === 'text' ? this.getClosestFractionValue(customValues, value) : this.getClosestValue(customValues, value);
|
|
123
126
|
|
|
124
127
|
return { value: closestValue.value, currentIndex: closestValue.index };
|
|
125
128
|
}
|
|
@@ -131,88 +134,141 @@ export class NumberTextFieldCustom extends React.Component {
|
|
|
131
134
|
customValues.reduce(
|
|
132
135
|
(closest, value, index) =>
|
|
133
136
|
Math.abs(value - number) < Math.abs(closest.value - number) ? { value, index } : closest,
|
|
134
|
-
{ value: customValues[0], index: 0 }
|
|
137
|
+
{ value: customValues[0], index: 0 },
|
|
135
138
|
);
|
|
136
139
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
getClosestFractionValue = (customValues, number) =>
|
|
141
|
+
customValues.reduce(
|
|
142
|
+
(closest, value, index) =>
|
|
143
|
+
Math.abs(math.number(math.fraction(value)) - math.number(math.fraction(number))) <
|
|
144
|
+
Math.abs(math.number(math.fraction(closest.value)) - math.number(math.fraction(number)))
|
|
145
|
+
? { value, index }
|
|
146
|
+
: closest,
|
|
147
|
+
{ value: customValues[0], index: 0 },
|
|
148
|
+
);
|
|
141
149
|
|
|
142
|
-
|
|
150
|
+
getValidFraction = (value) => {
|
|
151
|
+
if (this.isPositiveInteger(value.trim())) {
|
|
152
|
+
return value.trim();
|
|
153
|
+
}
|
|
154
|
+
if (value.trim() === '' || value.trim().split('/').length !== 2) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
let [numerator, denominator] = value.trim().split('/');
|
|
158
|
+
if (isNaN(numerator) || isNaN(denominator)) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
numerator = parseFloat(numerator);
|
|
162
|
+
denominator = parseFloat(denominator);
|
|
163
|
+
if (!Number.isInteger(numerator) || !Number.isInteger(denominator)) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (numerator < 0 || denominator < 1) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
return numerator + '/' + denominator;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
isPositiveInteger = (n) => {
|
|
173
|
+
return n >>> 0 === parseFloat(n);
|
|
174
|
+
};
|
|
143
175
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
176
|
+
onBlur = (event) => {
|
|
177
|
+
const { customValues, onlyIntegersAllowed, type } = this.props;
|
|
178
|
+
let { value } = event.target;
|
|
179
|
+
if (type === 'text') {
|
|
180
|
+
let tempValue = this.getValidFraction(value);
|
|
181
|
+
if (tempValue) {
|
|
182
|
+
value = tempValue;
|
|
183
|
+
} else {
|
|
184
|
+
value = this.props.value;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
let rawNumber = onlyIntegersAllowed ? Math.round(parseFloat(value)) : parseFloat(value);
|
|
188
|
+
if (type === 'text') {
|
|
189
|
+
rawNumber = value.trim();
|
|
152
190
|
}
|
|
191
|
+
const { value: number, currentIndex } = this.normalizeValueAndIndex(customValues, rawNumber);
|
|
192
|
+
this.setState(
|
|
193
|
+
{
|
|
194
|
+
value: number.toString(),
|
|
195
|
+
currentIndex,
|
|
196
|
+
},
|
|
197
|
+
() => this.props.onChange(event, number),
|
|
198
|
+
);
|
|
153
199
|
};
|
|
154
200
|
|
|
155
201
|
onChange(event) {
|
|
202
|
+
const { type } = this.props;
|
|
156
203
|
const { value } = event.target;
|
|
157
|
-
|
|
204
|
+
if (type !== 'text' && typeof value === 'string' && value.trim() === '') {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
158
207
|
this.setState({ value });
|
|
159
208
|
}
|
|
160
209
|
|
|
161
210
|
changeValue(event, sign = 1, shouldUpdate = false) {
|
|
162
211
|
event.preventDefault();
|
|
163
|
-
|
|
164
212
|
const { customValues, step, onlyIntegersAllowed, onChange } = this.props;
|
|
165
213
|
const { currentIndex, value } = this.state;
|
|
166
214
|
const updatedIndex = currentIndex + sign * 1;
|
|
167
215
|
let number;
|
|
168
|
-
|
|
169
216
|
if (customValues.length > 0) {
|
|
170
217
|
if (updatedIndex < 0 || updatedIndex >= customValues.length) {
|
|
171
218
|
return;
|
|
172
219
|
}
|
|
173
|
-
|
|
174
220
|
number = customValues[updatedIndex];
|
|
175
221
|
} else {
|
|
176
222
|
const rawNumber = onlyIntegersAllowed ? parseInt(value) : parseFloat(value);
|
|
177
223
|
const updatedValue = (rawNumber * 10000 + step * sign * 10000) / 10000;
|
|
178
224
|
number = this.clamp(updatedValue);
|
|
179
225
|
}
|
|
180
|
-
|
|
181
226
|
this.setState(
|
|
182
227
|
{
|
|
183
228
|
value: number.toString(),
|
|
184
|
-
currentIndex: updatedIndex
|
|
229
|
+
currentIndex: updatedIndex,
|
|
185
230
|
},
|
|
186
231
|
() => {
|
|
187
232
|
if (shouldUpdate) {
|
|
188
233
|
onChange(event, number);
|
|
189
234
|
}
|
|
190
|
-
}
|
|
235
|
+
},
|
|
191
236
|
);
|
|
192
237
|
}
|
|
193
238
|
|
|
194
239
|
render() {
|
|
195
240
|
const {
|
|
196
241
|
className,
|
|
197
|
-
classes,
|
|
198
242
|
label,
|
|
199
243
|
disabled,
|
|
200
244
|
error,
|
|
201
245
|
min,
|
|
202
246
|
max,
|
|
247
|
+
customValues,
|
|
203
248
|
inputClassName,
|
|
204
249
|
disableUnderline,
|
|
205
250
|
helperText,
|
|
206
251
|
variant,
|
|
207
|
-
textAlign
|
|
252
|
+
textAlign,
|
|
253
|
+
type = 'number',
|
|
208
254
|
} = this.props;
|
|
209
255
|
const { value } = this.state;
|
|
210
|
-
const names =
|
|
256
|
+
const names = className;
|
|
257
|
+
//Logic to disable the increment and decrement buttons
|
|
258
|
+
let disabledStart = false;
|
|
259
|
+
let disabledEnd = false;
|
|
260
|
+
if (customValues.length > 0) {
|
|
261
|
+
disabledStart = value === customValues[0];
|
|
262
|
+
disabledEnd = value === customValues[customValues.length - 1];
|
|
263
|
+
} else if (isFinite(min) && isFinite(max)) {
|
|
264
|
+
disabledStart = value === min;
|
|
265
|
+
disabledEnd = value === max;
|
|
266
|
+
}
|
|
211
267
|
|
|
212
268
|
return (
|
|
213
|
-
<
|
|
269
|
+
<StyledTextField
|
|
214
270
|
variant={variant}
|
|
215
|
-
inputRef={ref => (this.inputRef = ref)}
|
|
271
|
+
inputRef={(ref) => (this.inputRef = ref)}
|
|
216
272
|
disabled={disabled}
|
|
217
273
|
label={label}
|
|
218
274
|
value={value}
|
|
@@ -220,13 +276,13 @@ export class NumberTextFieldCustom extends React.Component {
|
|
|
220
276
|
helperText={helperText}
|
|
221
277
|
onChange={this.onChange}
|
|
222
278
|
onBlur={this.onBlur}
|
|
223
|
-
onKeyPress={e => {
|
|
279
|
+
onKeyPress={(e) => {
|
|
224
280
|
// once the Enter key is pressed, we force input blur
|
|
225
281
|
if (e.key === 'Enter' && this.inputRef) {
|
|
226
282
|
this.inputRef.blur();
|
|
227
283
|
}
|
|
228
284
|
}}
|
|
229
|
-
onKeyDown={e => {
|
|
285
|
+
onKeyDown={(e) => {
|
|
230
286
|
if (e.key === 'ArrowUp') {
|
|
231
287
|
this.changeValue(e);
|
|
232
288
|
}
|
|
@@ -235,42 +291,41 @@ export class NumberTextFieldCustom extends React.Component {
|
|
|
235
291
|
this.changeValue(e, -1);
|
|
236
292
|
}
|
|
237
293
|
}}
|
|
238
|
-
|
|
294
|
+
title={''}
|
|
295
|
+
type={type}
|
|
239
296
|
className={names}
|
|
240
297
|
InputProps={{
|
|
241
298
|
className: inputClassName,
|
|
242
299
|
disableUnderline: disableUnderline,
|
|
243
300
|
startAdornment: (
|
|
244
301
|
<InputAdornment position="start">
|
|
245
|
-
<
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
>
|
|
302
|
+
<StyledIconButton
|
|
303
|
+
disabled={disabled ? disabled : disabledStart}
|
|
304
|
+
onClick={(e) => this.changeValue(e, -1, true)}
|
|
305
|
+
size="large">
|
|
250
306
|
<Remove fontSize="small" />
|
|
251
|
-
</
|
|
307
|
+
</StyledIconButton>
|
|
252
308
|
</InputAdornment>
|
|
253
309
|
),
|
|
254
310
|
endAdornment: (
|
|
255
311
|
<InputAdornment position="end">
|
|
256
|
-
<
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
>
|
|
312
|
+
<StyledIconButton
|
|
313
|
+
disabled={disabled ? disabled : disabledEnd}
|
|
314
|
+
onClick={(e) => this.changeValue(e, 1, true)}
|
|
315
|
+
size="large">
|
|
261
316
|
<Add fontSize="small" />
|
|
262
|
-
</
|
|
317
|
+
</StyledIconButton>
|
|
263
318
|
</InputAdornment>
|
|
264
|
-
)
|
|
319
|
+
),
|
|
265
320
|
}}
|
|
266
321
|
inputProps={{
|
|
267
322
|
style: { textAlign },
|
|
268
323
|
min,
|
|
269
|
-
max
|
|
324
|
+
max,
|
|
270
325
|
}}
|
|
271
326
|
/>
|
|
272
327
|
);
|
|
273
328
|
}
|
|
274
329
|
}
|
|
275
330
|
|
|
276
|
-
export default
|
|
331
|
+
export default NumberTextFieldCustom;
|
|
@@ -1,16 +1,39 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import TextField from '@material
|
|
4
|
-
import
|
|
5
|
-
import { withStyles } from '@material-ui/core/styles';
|
|
3
|
+
import TextField from '@mui/material/TextField';
|
|
4
|
+
import { styled } from '@mui/material/styles';
|
|
6
5
|
import debug from 'debug';
|
|
7
6
|
import isFinite from 'lodash/isFinite';
|
|
8
|
-
import InputAdornment from '@material
|
|
7
|
+
import InputAdornment from '@mui/material/InputAdornment';
|
|
9
8
|
const log = debug('@pie-lib:config-ui:number-text-field');
|
|
10
9
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const StyledTextField = styled(TextField)(({ theme }) => ({
|
|
11
|
+
marginRight: theme.spacing(1),
|
|
12
|
+
'& .MuiInputLabel-root': {
|
|
13
|
+
width: 'auto',
|
|
14
|
+
minWidth: 'max-content',
|
|
15
|
+
maxWidth: 'none',
|
|
16
|
+
whiteSpace: 'nowrap',
|
|
17
|
+
overflow: 'visible',
|
|
18
|
+
transform: 'translate(0, 8px) scale(0.75)',
|
|
19
|
+
transformOrigin: 'top left',
|
|
20
|
+
position: 'relative',
|
|
21
|
+
},
|
|
22
|
+
'& .MuiInputBase-root, & .MuiInput-root, & .MuiFilledInput-root, & .MuiOutlinedInput-root': {
|
|
23
|
+
height: 'auto',
|
|
24
|
+
minHeight: 'auto',
|
|
25
|
+
},
|
|
26
|
+
'& .MuiInputBase-input': {
|
|
27
|
+
height: 'auto',
|
|
28
|
+
minHeight: 'auto',
|
|
29
|
+
padding: '8px 12px',
|
|
30
|
+
},
|
|
31
|
+
'& .MuiInput-root, & .MuiFilledInput-root': {
|
|
32
|
+
'&:before, &:after, &:hover:not(.Mui-disabled):before': {
|
|
33
|
+
display: 'none',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}));
|
|
14
37
|
|
|
15
38
|
const fallbackNumber = (min, max) => {
|
|
16
39
|
if (!isFinite(min) && !isFinite(max)) {
|
|
@@ -28,7 +51,6 @@ const fallbackNumber = (min, max) => {
|
|
|
28
51
|
export class NumberTextField extends React.Component {
|
|
29
52
|
static propTypes = {
|
|
30
53
|
disabled: PropTypes.bool,
|
|
31
|
-
classes: PropTypes.object.isRequired,
|
|
32
54
|
className: PropTypes.string,
|
|
33
55
|
inputClassName: PropTypes.string,
|
|
34
56
|
onChange: PropTypes.func.isRequired,
|
|
@@ -39,11 +61,11 @@ export class NumberTextField extends React.Component {
|
|
|
39
61
|
suffix: PropTypes.string,
|
|
40
62
|
showErrorWhenOutsideRange: PropTypes.bool,
|
|
41
63
|
disableUnderline: PropTypes.bool,
|
|
42
|
-
variant: PropTypes.string
|
|
64
|
+
variant: PropTypes.string,
|
|
43
65
|
};
|
|
44
66
|
|
|
45
67
|
static defaultProps = {
|
|
46
|
-
showErrorWhenOutsideRange: false
|
|
68
|
+
showErrorWhenOutsideRange: false,
|
|
47
69
|
};
|
|
48
70
|
|
|
49
71
|
constructor(props) {
|
|
@@ -52,7 +74,7 @@ export class NumberTextField extends React.Component {
|
|
|
52
74
|
const value = this.clamp(props.value);
|
|
53
75
|
|
|
54
76
|
this.state = {
|
|
55
|
-
value
|
|
77
|
+
value,
|
|
56
78
|
};
|
|
57
79
|
|
|
58
80
|
if (value !== props.value) {
|
|
@@ -63,23 +85,24 @@ export class NumberTextField extends React.Component {
|
|
|
63
85
|
}
|
|
64
86
|
|
|
65
87
|
UNSAFE_componentWillReceiveProps(props) {
|
|
66
|
-
const value = this.clamp(props.value);
|
|
88
|
+
const value = this.clamp(props.value, props.min, props.max);
|
|
89
|
+
|
|
67
90
|
this.setState({ value });
|
|
68
91
|
}
|
|
69
92
|
|
|
70
|
-
clamp(value) {
|
|
93
|
+
clamp(value, min = this.props.min, max = this.props.max) {
|
|
71
94
|
if (!isFinite(value)) {
|
|
72
|
-
return fallbackNumber(
|
|
95
|
+
return fallbackNumber(min, max);
|
|
73
96
|
}
|
|
74
97
|
|
|
75
|
-
const { min, max } = this.props;
|
|
76
|
-
|
|
77
98
|
if (isFinite(max)) {
|
|
78
99
|
value = Math.min(value, max);
|
|
79
100
|
}
|
|
101
|
+
|
|
80
102
|
if (isFinite(min)) {
|
|
81
103
|
value = Math.max(value, min);
|
|
82
104
|
}
|
|
105
|
+
|
|
83
106
|
return value;
|
|
84
107
|
}
|
|
85
108
|
|
|
@@ -87,7 +110,7 @@ export class NumberTextField extends React.Component {
|
|
|
87
110
|
* on Blur (this can be triggered by pressing Enter, see below)
|
|
88
111
|
* we check the entered value and reset it if needed
|
|
89
112
|
*/
|
|
90
|
-
onBlur = event => {
|
|
113
|
+
onBlur = (event) => {
|
|
91
114
|
const value = event.target.value;
|
|
92
115
|
|
|
93
116
|
const rawNumber = parseFloat(value);
|
|
@@ -140,7 +163,6 @@ export class NumberTextField extends React.Component {
|
|
|
140
163
|
render() {
|
|
141
164
|
const {
|
|
142
165
|
className,
|
|
143
|
-
classes,
|
|
144
166
|
label,
|
|
145
167
|
disabled,
|
|
146
168
|
suffix,
|
|
@@ -149,43 +171,43 @@ export class NumberTextField extends React.Component {
|
|
|
149
171
|
inputClassName,
|
|
150
172
|
disableUnderline,
|
|
151
173
|
showErrorWhenOutsideRange,
|
|
152
|
-
variant
|
|
174
|
+
variant,
|
|
153
175
|
} = this.props;
|
|
154
|
-
const names = classNames(classes.root, className);
|
|
155
176
|
|
|
156
177
|
const error = showErrorWhenOutsideRange && this.getError();
|
|
157
178
|
return (
|
|
158
|
-
<
|
|
159
|
-
variant={variant || 'standard'}
|
|
160
|
-
inputRef={ref => {
|
|
179
|
+
<StyledTextField
|
|
180
|
+
variant={disableUnderline ? 'filled' : (variant || 'standard')}
|
|
181
|
+
inputRef={(ref) => {
|
|
161
182
|
this.inputRef = ref;
|
|
162
183
|
}}
|
|
163
184
|
disabled={disabled}
|
|
164
185
|
label={label}
|
|
186
|
+
InputLabelProps={{
|
|
187
|
+
shrink: true,
|
|
188
|
+
}}
|
|
165
189
|
value={this.state.value}
|
|
166
190
|
error={!!error}
|
|
167
191
|
helperText={error}
|
|
168
192
|
onChange={this.onChange}
|
|
169
193
|
onBlur={this.onBlur}
|
|
170
|
-
|
|
194
|
+
onKeyDown={(e) => {
|
|
171
195
|
// once the Enter key is pressed, we force input blur
|
|
172
196
|
if (e.key === 'Enter' && this.inputRef) {
|
|
173
197
|
this.inputRef.blur();
|
|
174
198
|
}
|
|
175
199
|
}}
|
|
176
200
|
type="number"
|
|
177
|
-
className={
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
min,
|
|
188
|
-
max
|
|
201
|
+
className={className}
|
|
202
|
+
slotProps={{
|
|
203
|
+
input: {
|
|
204
|
+
endAdornment: suffix && <InputAdornment position="end">{suffix}</InputAdornment>,
|
|
205
|
+
className: inputClassName,
|
|
206
|
+
inputProps: {
|
|
207
|
+
min,
|
|
208
|
+
max,
|
|
209
|
+
},
|
|
210
|
+
},
|
|
189
211
|
}}
|
|
190
212
|
margin="normal"
|
|
191
213
|
/>
|
|
@@ -193,4 +215,4 @@ export class NumberTextField extends React.Component {
|
|
|
193
215
|
}
|
|
194
216
|
}
|
|
195
217
|
|
|
196
|
-
export default
|
|
218
|
+
export default NumberTextField;
|
package/src/radio-with-label.jsx
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
|
-
import FormControlLabel from '@material
|
|
2
|
-
import Radio from '@material
|
|
1
|
+
import FormControlLabel from '@mui/material/FormControlLabel';
|
|
2
|
+
import Radio from '@mui/material/Radio';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import { styled } from '@mui/material/styles';
|
|
6
|
+
import { color } from '@pie-lib/render-ui';
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
label: {
|
|
8
|
+
const StyledFormControlLabel = styled(FormControlLabel)(() => ({
|
|
9
|
+
'& .MuiFormControlLabel-label': {
|
|
8
10
|
left: '-5px',
|
|
9
|
-
position: 'relative'
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
|
|
11
|
+
position: 'relative',
|
|
12
|
+
},
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
const StyledRadio = styled(Radio)(() => ({
|
|
16
|
+
color: `${color.tertiary()} !important`,
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const RadioWithLabel = ({ label, value, checked, onChange }) => (
|
|
20
|
+
<StyledFormControlLabel
|
|
13
21
|
value={value}
|
|
14
|
-
|
|
15
|
-
control={<Radio checked={checked} onChange={onChange} />}
|
|
22
|
+
control={<StyledRadio checked={checked} onChange={onChange} />}
|
|
16
23
|
label={label}
|
|
17
24
|
/>
|
|
18
|
-
)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
RadioWithLabel.propTypes = {
|
|
28
|
+
label: PropTypes.string,
|
|
29
|
+
value: PropTypes.string,
|
|
30
|
+
checked: PropTypes.bool,
|
|
31
|
+
onChange: PropTypes.func,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default RadioWithLabel;
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import Typography from '@material
|
|
4
|
-
import {
|
|
3
|
+
import Typography from '@mui/material/Typography';
|
|
4
|
+
import { styled } from '@mui/material/styles';
|
|
5
5
|
import NumberTextField from '../number-text-field';
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
const StyledDisplaySize = styled('div')(({ theme }) => ({
|
|
8
|
+
display: 'flex',
|
|
9
|
+
paddingTop: theme.spacing(1),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
const DisplaySize = ({ size, label, onChange }) => {
|
|
13
13
|
const updateSize = (key, v) => {
|
|
14
14
|
onChange({ ...size, [key]: v });
|
|
15
15
|
};
|
|
16
|
+
|
|
16
17
|
return (
|
|
17
18
|
<div>
|
|
18
19
|
<Typography>{label}</Typography>
|
|
19
|
-
<
|
|
20
|
+
<StyledDisplaySize>
|
|
20
21
|
<NumberTextField
|
|
21
22
|
label="Width"
|
|
22
23
|
type="number"
|
|
@@ -35,18 +36,18 @@ const DisplaySize = withStyles(theme => ({
|
|
|
35
36
|
value={size.height}
|
|
36
37
|
onChange={(e, v) => updateSize('height', v)}
|
|
37
38
|
/>
|
|
38
|
-
</
|
|
39
|
+
</StyledDisplaySize>
|
|
39
40
|
</div>
|
|
40
41
|
);
|
|
41
|
-
}
|
|
42
|
+
};
|
|
42
43
|
|
|
43
44
|
DisplaySize.propTypes = {
|
|
44
45
|
size: PropTypes.shape({
|
|
45
46
|
width: PropTypes.number.isRequired,
|
|
46
|
-
height: PropTypes.number.isRequired
|
|
47
|
+
height: PropTypes.number.isRequired,
|
|
47
48
|
}).isRequired,
|
|
48
49
|
label: PropTypes.string.isRequired,
|
|
49
|
-
onChange: PropTypes.func
|
|
50
|
+
onChange: PropTypes.func,
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
export default DisplaySize;
|