@pie-lib/config-ui 10.10.4-next.50 → 10.10.4-next.501
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.md +346 -0
- package/lib/alert-dialog.js +44 -0
- package/lib/alert-dialog.js.map +1 -0
- package/lib/checkbox.js +4 -4
- package/lib/checkbox.js.map +1 -1
- package/lib/choice-configuration/feedback-menu.js +41 -53
- package/lib/choice-configuration/feedback-menu.js.map +1 -1
- package/lib/choice-configuration/index.js +88 -81
- package/lib/choice-configuration/index.js.map +1 -1
- package/lib/choice-utils.js +8 -8
- package/lib/choice-utils.js.map +1 -1
- package/lib/feedback-config/feedback-selector.js +38 -47
- package/lib/feedback-config/feedback-selector.js.map +1 -1
- package/lib/feedback-config/group.js +5 -5
- package/lib/feedback-config/group.js.map +1 -1
- package/lib/feedback-config/index.js +46 -52
- package/lib/feedback-config/index.js.map +1 -1
- package/lib/form-section.js +8 -6
- package/lib/form-section.js.map +1 -1
- package/lib/help.js +30 -37
- package/lib/help.js.map +1 -1
- package/lib/index.js +66 -45
- package/lib/index.js.map +1 -1
- package/lib/input.js +35 -40
- package/lib/input.js.map +1 -1
- package/lib/inputs.js +28 -17
- package/lib/inputs.js.map +1 -1
- package/lib/langs.js +37 -45
- package/lib/langs.js.map +1 -1
- package/lib/layout/config-layout.js +29 -37
- package/lib/layout/config-layout.js.map +1 -1
- package/lib/layout/index.js +2 -2
- package/lib/layout/index.js.map +1 -1
- package/lib/layout/layout-contents.js +28 -34
- package/lib/layout/layout-contents.js.map +1 -1
- package/lib/layout/settings-box.js +23 -31
- package/lib/layout/settings-box.js.map +1 -1
- package/lib/mui-box/index.js +3 -3
- package/lib/mui-box/index.js.map +1 -1
- package/lib/number-text-field-custom.js +364 -0
- package/lib/number-text-field-custom.js.map +1 -0
- package/lib/number-text-field.js +33 -42
- package/lib/number-text-field.js.map +1 -1
- package/lib/radio-with-label.js +4 -4
- package/lib/radio-with-label.js.map +1 -1
- package/lib/settings/display-size.js +10 -10
- package/lib/settings/display-size.js.map +1 -1
- package/lib/settings/index.js +11 -17
- package/lib/settings/index.js.map +1 -1
- package/lib/settings/panel.js +58 -68
- package/lib/settings/panel.js.map +1 -1
- package/lib/settings/settings-radio-label.js +4 -4
- package/lib/settings/settings-radio-label.js.map +1 -1
- package/lib/settings/toggle.js +5 -5
- package/lib/settings/toggle.js.map +1 -1
- package/lib/tabs/index.js +28 -35
- package/lib/tabs/index.js.map +1 -1
- package/lib/tags-input/index.js +32 -40
- package/lib/tags-input/index.js.map +1 -1
- package/lib/two-choice.js +38 -48
- package/lib/two-choice.js.map +1 -1
- package/lib/with-stateful-model.js +23 -30
- package/lib/with-stateful-model.js.map +1 -1
- package/package.json +4 -4
- package/src/alert-dialog.jsx +43 -0
- package/src/choice-configuration/index.jsx +30 -11
- package/src/form-section.jsx +2 -2
- package/src/index.js +4 -0
- package/src/inputs.jsx +13 -5
- package/src/number-text-field-custom.jsx +276 -0
|
@@ -1,64 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
3
5
|
Object.defineProperty(exports, "__esModule", {
|
|
4
6
|
value: true
|
|
5
7
|
});
|
|
6
8
|
exports["default"] = void 0;
|
|
7
9
|
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
24
|
+
var _react = _interopRequireDefault(require("react"));
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
29
27
|
|
|
30
|
-
function
|
|
28
|
+
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
|
|
31
29
|
|
|
32
|
-
function
|
|
30
|
+
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
33
31
|
|
|
34
32
|
var withStatefulModel = function withStatefulModel(Component) {
|
|
35
|
-
var Stateful =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
var Stateful = /*#__PURE__*/function (_React$Component) {
|
|
34
|
+
(0, _inherits2["default"])(Stateful, _React$Component);
|
|
35
|
+
|
|
36
|
+
var _super = _createSuper(Stateful);
|
|
39
37
|
|
|
40
38
|
function Stateful(props) {
|
|
41
39
|
var _this;
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
_defineProperty(_assertThisInitialized(_this), "onChange", function (model) {
|
|
41
|
+
(0, _classCallCheck2["default"])(this, Stateful);
|
|
42
|
+
_this = _super.call(this, props);
|
|
43
|
+
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onChange", function (model) {
|
|
48
44
|
_this.setState({
|
|
49
45
|
model: model
|
|
50
46
|
}, function () {
|
|
51
47
|
_this.props.onChange(_this.state.model);
|
|
52
48
|
});
|
|
53
49
|
});
|
|
54
|
-
|
|
55
50
|
_this.state = {
|
|
56
51
|
model: props.model
|
|
57
52
|
};
|
|
58
53
|
return _this;
|
|
59
54
|
}
|
|
60
55
|
|
|
61
|
-
|
|
56
|
+
(0, _createClass2["default"])(Stateful, [{
|
|
62
57
|
key: "componentWillReceiveProps",
|
|
63
58
|
value: function componentWillReceiveProps(props) {
|
|
64
59
|
this.setState({
|
|
@@ -68,21 +63,19 @@ var withStatefulModel = function withStatefulModel(Component) {
|
|
|
68
63
|
}, {
|
|
69
64
|
key: "render",
|
|
70
65
|
value: function render() {
|
|
71
|
-
return _react["default"].createElement(Component, {
|
|
66
|
+
return /*#__PURE__*/_react["default"].createElement(Component, {
|
|
72
67
|
model: this.state.model,
|
|
73
68
|
onChange: this.onChange
|
|
74
69
|
});
|
|
75
70
|
}
|
|
76
71
|
}]);
|
|
77
|
-
|
|
78
72
|
return Stateful;
|
|
79
73
|
}(_react["default"].Component);
|
|
80
74
|
|
|
81
|
-
|
|
75
|
+
(0, _defineProperty2["default"])(Stateful, "propTypes", {
|
|
82
76
|
model: _propTypes["default"].object.isRequired,
|
|
83
77
|
onChange: _propTypes["default"].func.isRequired
|
|
84
78
|
});
|
|
85
|
-
|
|
86
79
|
return Stateful;
|
|
87
80
|
};
|
|
88
81
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"with-stateful-model.js","names":["withStatefulModel","Component","Stateful","props","model","setState","onChange","state","React","PropTypes","object","isRequired","func"],"sources":["../src/with-stateful-model.jsx"],"sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst withStatefulModel = Component => {\n class Stateful extends React.Component {\n static propTypes = {\n model: PropTypes.object.isRequired,\n onChange: PropTypes.func.isRequired\n };\n\n constructor(props) {\n super(props);\n this.state = {\n model: props.model\n };\n }\n\n componentWillReceiveProps(props) {\n this.setState({ model: props.model });\n }\n\n onChange = model => {\n this.setState({ model }, () => {\n this.props.onChange(this.state.model);\n });\n };\n\n render() {\n return <Component model={this.state.model} onChange={this.onChange} />;\n }\n }\n\n return Stateful;\n};\n\nexport default withStatefulModel;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;;;;;AAEA,IAAMA,iBAAiB,GAAG,SAApBA,iBAAoB,CAAAC,SAAS,EAAI;EAAA,IAC/BC,QAD+B;IAAA;;IAAA;;IAOnC,kBAAYC,KAAZ,EAAmB;MAAA;;MAAA;MACjB,0BAAMA,KAAN;MADiB,6FAWR,UAAAC,KAAK,EAAI;QAClB,MAAKC,QAAL,CAAc;UAAED,KAAK,EAALA;QAAF,CAAd,EAAyB,YAAM;UAC7B,MAAKD,KAAL,CAAWG,QAAX,CAAoB,MAAKC,KAAL,CAAWH,KAA/B;QACD,CAFD;MAGD,CAfkB;MAEjB,MAAKG,KAAL,GAAa;QACXH,KAAK,EAAED,KAAK,CAACC;MADF,CAAb;MAFiB;IAKlB;;IAZkC;MAAA;MAAA,OAcnC,mCAA0BD,KAA1B,EAAiC;QAC/B,KAAKE,QAAL,CAAc;UAAED,KAAK,EAAED,KAAK,CAACC;QAAf,CAAd;MACD;IAhBkC;MAAA;MAAA,OAwBnC,kBAAS;QACP,oBAAO,gCAAC,SAAD;UAAW,KAAK,EAAE,KAAKG,KAAL,CAAWH,KAA7B;UAAoC,QAAQ,EAAE,KAAKE;QAAnD,EAAP;MACD;IA1BkC;IAAA;EAAA,EACdE,iBAAA,CAAMP,SADQ;;EAAA,iCAC/BC,QAD+B,eAEhB;IACjBE,KAAK,EAAEK,qBAAA,CAAUC,MAAV,CAAiBC,UADP;IAEjBL,QAAQ,EAAEG,qBAAA,CAAUG,IAAV,CAAeD;EAFR,CAFgB;EA6BrC,OAAOT,QAAP;AACD,CA9BD;;eAgCeF,iB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-lib/config-ui",
|
|
3
|
-
"version": "10.10.4-next.
|
|
3
|
+
"version": "10.10.4-next.501+5dbb5690",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"module": "src/index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@material-ui/core": "^3.8.3",
|
|
12
12
|
"@material-ui/icons": "^3.0.2",
|
|
13
|
-
"@pie-lib/editable-html": "^7.17.4-next.
|
|
13
|
+
"@pie-lib/editable-html": "^7.17.4-next.501+5dbb5690",
|
|
14
14
|
"@pie-lib/icons": "^2.4.25",
|
|
15
|
-
"@pie-lib/render-ui": "^4.
|
|
15
|
+
"@pie-lib/render-ui": "^4.13.1",
|
|
16
16
|
"classnames": "^2.2.6",
|
|
17
17
|
"debug": "^4.1.1",
|
|
18
18
|
"lodash": "^4.17.11",
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"react": "^16.8.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "5dbb56906290d5145ca6de59df2566a7e8b0e916"
|
|
30
30
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
Dialog,
|
|
6
|
+
DialogActions,
|
|
7
|
+
DialogContent,
|
|
8
|
+
DialogContentText,
|
|
9
|
+
DialogTitle
|
|
10
|
+
} from '@material-ui/core';
|
|
11
|
+
|
|
12
|
+
const AlertDialog = ({ text, title, onClose, onConfirm, open }) => (
|
|
13
|
+
<Dialog open={open} onClose={onClose}>
|
|
14
|
+
{title && <DialogTitle>{title}</DialogTitle>}
|
|
15
|
+
{text && (
|
|
16
|
+
<DialogContent>
|
|
17
|
+
<DialogContentText>{text}</DialogContentText>
|
|
18
|
+
</DialogContent>
|
|
19
|
+
)}
|
|
20
|
+
<DialogActions>
|
|
21
|
+
{onClose && (
|
|
22
|
+
<Button onClick={onClose} color="primary">
|
|
23
|
+
CANCEL
|
|
24
|
+
</Button>
|
|
25
|
+
)}
|
|
26
|
+
{onConfirm && (
|
|
27
|
+
<Button autoFocus onClick={onConfirm} color="primary">
|
|
28
|
+
OK
|
|
29
|
+
</Button>
|
|
30
|
+
)}
|
|
31
|
+
</DialogActions>
|
|
32
|
+
</Dialog>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
AlertDialog.propTypes = {
|
|
36
|
+
text: PropTypes.string,
|
|
37
|
+
title: PropTypes.string,
|
|
38
|
+
onClose: PropTypes.func,
|
|
39
|
+
onConfirm: PropTypes.func,
|
|
40
|
+
open: PropTypes.bool
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default AlertDialog;
|
|
@@ -18,16 +18,20 @@ const EditableHtmlContainer = withStyles(theme => ({
|
|
|
18
18
|
}
|
|
19
19
|
}))(
|
|
20
20
|
({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
label,
|
|
22
|
+
classes,
|
|
23
|
+
onChange,
|
|
24
|
+
value,
|
|
25
|
+
className,
|
|
26
|
+
imageSupport,
|
|
27
|
+
disabled,
|
|
28
|
+
spellCheck,
|
|
29
|
+
nonEmpty,
|
|
30
|
+
toolbarOpts,
|
|
31
|
+
error,
|
|
32
|
+
maxImageWidth,
|
|
33
|
+
maxImageHeight
|
|
34
|
+
}) => {
|
|
31
35
|
const names = classNames(classes.labelContainer, className);
|
|
32
36
|
|
|
33
37
|
return (
|
|
@@ -36,11 +40,15 @@ const EditableHtmlContainer = withStyles(theme => ({
|
|
|
36
40
|
<EditableHtml
|
|
37
41
|
markup={value || ''}
|
|
38
42
|
disabled={disabled}
|
|
43
|
+
spellCheck={spellCheck}
|
|
39
44
|
nonEmpty={nonEmpty}
|
|
40
45
|
onChange={onChange}
|
|
41
46
|
imageSupport={imageSupport}
|
|
42
47
|
className={classes.editor}
|
|
43
48
|
toolbarOpts={toolbarOpts}
|
|
49
|
+
error={error}
|
|
50
|
+
maxImageWidth={maxImageWidth}
|
|
51
|
+
maxImageHeight={maxImageHeight}
|
|
44
52
|
/>
|
|
45
53
|
</div>
|
|
46
54
|
</InputContainer>
|
|
@@ -183,10 +191,13 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
183
191
|
useLetterOrdering,
|
|
184
192
|
imageSupport,
|
|
185
193
|
disabled,
|
|
194
|
+
spellCheck,
|
|
186
195
|
nonEmpty,
|
|
187
196
|
allowFeedBack,
|
|
188
197
|
allowDelete,
|
|
189
|
-
toolbarOpts
|
|
198
|
+
toolbarOpts,
|
|
199
|
+
error,
|
|
200
|
+
noCorrectAnswerError
|
|
190
201
|
} = this.props;
|
|
191
202
|
|
|
192
203
|
const InputToggle = mode === 'checkbox' ? InputCheckbox : InputRadio;
|
|
@@ -204,6 +215,7 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
204
215
|
onChange={this.onCheckedChange}
|
|
205
216
|
label={!noLabels ? 'Correct' : ''}
|
|
206
217
|
checked={!!data.correct}
|
|
218
|
+
error={noCorrectAnswerError}
|
|
207
219
|
/>
|
|
208
220
|
<div className={classes.middleColumn}>
|
|
209
221
|
<EditableHtmlContainer
|
|
@@ -212,9 +224,12 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
212
224
|
onChange={this.onLabelChange}
|
|
213
225
|
imageSupport={imageSupport}
|
|
214
226
|
disabled={disabled}
|
|
227
|
+
spellCheck={spellCheck}
|
|
215
228
|
nonEmpty={nonEmpty}
|
|
216
229
|
toolbarOpts={toolbarOpts}
|
|
230
|
+
error={error}
|
|
217
231
|
/>
|
|
232
|
+
{error && <div className={classes.errorText}>{error}</div>}
|
|
218
233
|
|
|
219
234
|
{allowFeedBack && (
|
|
220
235
|
<Feedback
|
|
@@ -294,6 +309,10 @@ const styles = theme => ({
|
|
|
294
309
|
display: 'flex',
|
|
295
310
|
flex: 1,
|
|
296
311
|
flexDirection: 'column'
|
|
312
|
+
},
|
|
313
|
+
errorText: {
|
|
314
|
+
fontSize: '12px',
|
|
315
|
+
color: 'red'
|
|
297
316
|
}
|
|
298
317
|
});
|
|
299
318
|
|
package/src/form-section.jsx
CHANGED
|
@@ -13,9 +13,9 @@ const styles = theme => ({
|
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
export default withStyles(styles)(({ className, classes, label, children }) => (
|
|
16
|
+
export default withStyles(styles)(({ className, classes, label, children, labelExtraStyle }) => (
|
|
17
17
|
<div className={classNames(classes.formSection, className)}>
|
|
18
|
-
<Typography className={classes.label} type="subheading">
|
|
18
|
+
<Typography className={classes.label} type="subheading" style={labelExtraStyle}>
|
|
19
19
|
{label}
|
|
20
20
|
</Typography>
|
|
21
21
|
{children}
|
package/src/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import AlertDialog from './alert-dialog';
|
|
1
2
|
import FeedbackConfig, {
|
|
2
3
|
FeedbackSelector,
|
|
3
4
|
buildDefaults as feedbackConfigDefaults
|
|
@@ -11,6 +12,7 @@ import Help from './help';
|
|
|
11
12
|
import Input from './input';
|
|
12
13
|
import { InputContainer } from '@pie-lib/render-ui';
|
|
13
14
|
import NumberTextField from './number-text-field';
|
|
15
|
+
import NumberTextFieldCustom from './number-text-field-custom';
|
|
14
16
|
import TwoChoice, { NChoice } from './two-choice';
|
|
15
17
|
import TagsInput from './tags-input';
|
|
16
18
|
import MuiBox from './mui-box';
|
|
@@ -25,6 +27,7 @@ import DisplaySize from './settings/display-size';
|
|
|
25
27
|
import * as settings from './settings';
|
|
26
28
|
|
|
27
29
|
export {
|
|
30
|
+
AlertDialog,
|
|
28
31
|
FeedbackConfig,
|
|
29
32
|
FeedbackSelector,
|
|
30
33
|
feedbackConfigDefaults,
|
|
@@ -40,6 +43,7 @@ export {
|
|
|
40
43
|
Input,
|
|
41
44
|
InputContainer,
|
|
42
45
|
NumberTextField,
|
|
46
|
+
NumberTextFieldCustom,
|
|
43
47
|
TwoChoice,
|
|
44
48
|
NChoice,
|
|
45
49
|
TagsInput,
|
package/src/inputs.jsx
CHANGED
|
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import Switch from '@material-ui/core/Switch';
|
|
7
7
|
import { withStyles } from '@material-ui/core/styles';
|
|
8
|
+
import classNames from 'classnames';
|
|
8
9
|
|
|
9
10
|
const InputTypes = {
|
|
10
11
|
classes: PropTypes.object.isRequired,
|
|
@@ -12,7 +13,8 @@ const InputTypes = {
|
|
|
12
13
|
label: PropTypes.string,
|
|
13
14
|
checked: PropTypes.bool,
|
|
14
15
|
onChange: PropTypes.func,
|
|
15
|
-
disabled: PropTypes.bool
|
|
16
|
+
disabled: PropTypes.bool,
|
|
17
|
+
error: PropTypes.string
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
const RawInputSwitch = ({ classes, className, label, checked, onChange }) => {
|
|
@@ -38,12 +40,12 @@ const InputSwitch = withStyles({
|
|
|
38
40
|
})(RawInputSwitch);
|
|
39
41
|
|
|
40
42
|
const RawInputCheckbox = props => {
|
|
41
|
-
const { classes, className, label, checked, onChange, disabled } = props;
|
|
43
|
+
const { classes, className, label, checked, onChange, disabled, error } = props;
|
|
42
44
|
|
|
43
45
|
return (
|
|
44
46
|
<InputContainer className={className} label={label}>
|
|
45
47
|
<Checkbox
|
|
46
|
-
className={classes.checkboxRoot}
|
|
48
|
+
className={classNames(classes.checkboxRoot, error && classes.error)}
|
|
47
49
|
disabled={disabled}
|
|
48
50
|
checked={checked}
|
|
49
51
|
onChange={onChange}
|
|
@@ -56,12 +58,12 @@ const RawInputCheckbox = props => {
|
|
|
56
58
|
RawInputCheckbox.propTypes = { ...InputTypes };
|
|
57
59
|
|
|
58
60
|
const RawInputRadio = props => {
|
|
59
|
-
const { classes, className, label, checked, onChange, disabled } = props;
|
|
61
|
+
const { classes, className, label, checked, onChange, disabled, error } = props;
|
|
60
62
|
|
|
61
63
|
return (
|
|
62
64
|
<InputContainer className={className} label={label}>
|
|
63
65
|
<Radio
|
|
64
|
-
className={classes.radioRoot}
|
|
66
|
+
className={classNames(classes.radioRoot, error && classes.error)}
|
|
65
67
|
disabled={disabled}
|
|
66
68
|
checked={checked}
|
|
67
69
|
onChange={onChange}
|
|
@@ -76,12 +78,18 @@ RawInputRadio.propTypes = { ...InputTypes };
|
|
|
76
78
|
const InputCheckbox = withStyles({
|
|
77
79
|
checkboxRoot: {
|
|
78
80
|
transform: 'translate(-25%, 20%)'
|
|
81
|
+
},
|
|
82
|
+
error: {
|
|
83
|
+
color: 'red'
|
|
79
84
|
}
|
|
80
85
|
})(RawInputCheckbox);
|
|
81
86
|
|
|
82
87
|
const InputRadio = withStyles(() => ({
|
|
83
88
|
radioRoot: {
|
|
84
89
|
transform: 'translate(-20%, 20%)'
|
|
90
|
+
},
|
|
91
|
+
error: {
|
|
92
|
+
color: 'red'
|
|
85
93
|
}
|
|
86
94
|
}))(RawInputRadio);
|
|
87
95
|
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import TextField from '@material-ui/core/TextField';
|
|
4
|
+
import classNames from 'classnames';
|
|
5
|
+
import { withStyles } from '@material-ui/core/styles';
|
|
6
|
+
import isFinite from 'lodash/isFinite';
|
|
7
|
+
import IconButton from '@material-ui/core/IconButton';
|
|
8
|
+
import InputAdornment from '@material-ui/core/InputAdornment';
|
|
9
|
+
import Remove from '@material-ui/icons/Remove';
|
|
10
|
+
import Add from '@material-ui/icons/Add';
|
|
11
|
+
|
|
12
|
+
const styles = theme => ({
|
|
13
|
+
input: {
|
|
14
|
+
'& input[type=number]': {
|
|
15
|
+
'-moz-appearance': 'textfield'
|
|
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
|
+
}
|
|
25
|
+
},
|
|
26
|
+
iconButton: {
|
|
27
|
+
padding: '2px'
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const fallbackNumber = (min, max) => {
|
|
32
|
+
if (!isFinite(min) && !isFinite(max)) {
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!isFinite(min) && isFinite(max)) {
|
|
37
|
+
return max;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (isFinite(min)) {
|
|
41
|
+
return min;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export class NumberTextFieldCustom extends React.Component {
|
|
46
|
+
static propTypes = {
|
|
47
|
+
classes: PropTypes.object.isRequired,
|
|
48
|
+
className: PropTypes.string,
|
|
49
|
+
customValues: PropTypes.array,
|
|
50
|
+
disabled: PropTypes.bool,
|
|
51
|
+
error: PropTypes.bool,
|
|
52
|
+
inputClassName: PropTypes.string,
|
|
53
|
+
onChange: PropTypes.func.isRequired,
|
|
54
|
+
onlyIntegersAllowed: PropTypes.bool,
|
|
55
|
+
value: PropTypes.number,
|
|
56
|
+
min: PropTypes.number,
|
|
57
|
+
max: PropTypes.number,
|
|
58
|
+
step: PropTypes.number,
|
|
59
|
+
label: PropTypes.string,
|
|
60
|
+
disableUnderline: PropTypes.bool,
|
|
61
|
+
variant: PropTypes.string
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
static defaultProps = {
|
|
65
|
+
step: 1,
|
|
66
|
+
customValues: [],
|
|
67
|
+
textAlign: 'center',
|
|
68
|
+
variant: 'standard',
|
|
69
|
+
onlyIntegersAllowed: false
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
constructor(props) {
|
|
73
|
+
super(props);
|
|
74
|
+
|
|
75
|
+
const { value, currentIndex } = this.normalizeValueAndIndex(props.customValues, props.value);
|
|
76
|
+
|
|
77
|
+
this.state = {
|
|
78
|
+
value,
|
|
79
|
+
currentIndex
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (value !== props.value) {
|
|
83
|
+
this.props.onChange({}, value);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.onChange = this.onChange.bind(this);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
UNSAFE_componentWillReceiveProps(props) {
|
|
90
|
+
const { value, currentIndex } = this.normalizeValueAndIndex(props.customValues, props.value);
|
|
91
|
+
|
|
92
|
+
this.setState({ value, currentIndex });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
clamp(value) {
|
|
96
|
+
const { min, max, customValues } = this.props;
|
|
97
|
+
|
|
98
|
+
if ((customValues || []).length > 0) {
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!isFinite(value)) {
|
|
103
|
+
return fallbackNumber(min, max);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isFinite(max)) {
|
|
107
|
+
value = Math.min(value, max);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (isFinite(min)) {
|
|
111
|
+
value = Math.max(value, min);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
normalizeValueAndIndex = (customValues, number) => {
|
|
118
|
+
const value = this.clamp(number);
|
|
119
|
+
const currentIndex = (customValues || []).findIndex(val => val === value);
|
|
120
|
+
|
|
121
|
+
if ((customValues || []).length > 0 && currentIndex === -1) {
|
|
122
|
+
const closestValue = this.getClosestValue(customValues, value);
|
|
123
|
+
|
|
124
|
+
return { value: closestValue.value, currentIndex: closestValue.index };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { value, currentIndex };
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
getClosestValue = (customValues, number) =>
|
|
131
|
+
customValues.reduce(
|
|
132
|
+
(closest, value, index) =>
|
|
133
|
+
Math.abs(value - number) < Math.abs(closest.value - number) ? { value, index } : closest,
|
|
134
|
+
{ value: customValues[0], index: 0 }
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
onBlur = event => {
|
|
138
|
+
const { customValues, onlyIntegersAllowed } = this.props;
|
|
139
|
+
const { value } = event.target;
|
|
140
|
+
const rawNumber = onlyIntegersAllowed ? parseInt(value) : parseFloat(value);
|
|
141
|
+
|
|
142
|
+
const { value: number, currentIndex } = this.normalizeValueAndIndex(customValues, rawNumber);
|
|
143
|
+
|
|
144
|
+
if (number !== this.state.value) {
|
|
145
|
+
this.setState(
|
|
146
|
+
{
|
|
147
|
+
value: number.toString(),
|
|
148
|
+
currentIndex
|
|
149
|
+
},
|
|
150
|
+
() => this.props.onChange(event, number)
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
onChange(event) {
|
|
156
|
+
const { value } = event.target;
|
|
157
|
+
|
|
158
|
+
this.setState({ value });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
changeValue(event, sign = 1, shouldUpdate = false) {
|
|
162
|
+
event.preventDefault();
|
|
163
|
+
|
|
164
|
+
const { customValues, step, onlyIntegersAllowed, onChange } = this.props;
|
|
165
|
+
const { currentIndex, value } = this.state;
|
|
166
|
+
const updatedIndex = currentIndex + sign * 1;
|
|
167
|
+
let number;
|
|
168
|
+
|
|
169
|
+
if (customValues.length > 0) {
|
|
170
|
+
if (updatedIndex < 0 || updatedIndex >= customValues.length) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
number = customValues[updatedIndex];
|
|
175
|
+
} else {
|
|
176
|
+
const rawNumber = onlyIntegersAllowed ? parseInt(value) : parseFloat(value);
|
|
177
|
+
const updatedValue = (rawNumber * 10000 + step * sign * 10000) / 10000;
|
|
178
|
+
number = this.clamp(updatedValue);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this.setState(
|
|
182
|
+
{
|
|
183
|
+
value: number.toString(),
|
|
184
|
+
currentIndex: updatedIndex
|
|
185
|
+
},
|
|
186
|
+
() => {
|
|
187
|
+
if (shouldUpdate) {
|
|
188
|
+
onChange(event, number);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
render() {
|
|
195
|
+
const {
|
|
196
|
+
className,
|
|
197
|
+
classes,
|
|
198
|
+
label,
|
|
199
|
+
disabled,
|
|
200
|
+
error,
|
|
201
|
+
min,
|
|
202
|
+
max,
|
|
203
|
+
inputClassName,
|
|
204
|
+
disableUnderline,
|
|
205
|
+
helperText,
|
|
206
|
+
variant,
|
|
207
|
+
textAlign
|
|
208
|
+
} = this.props;
|
|
209
|
+
const { value } = this.state;
|
|
210
|
+
const names = classNames(className, classes.input);
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<TextField
|
|
214
|
+
variant={variant}
|
|
215
|
+
inputRef={ref => (this.inputRef = ref)}
|
|
216
|
+
disabled={disabled}
|
|
217
|
+
label={label}
|
|
218
|
+
value={value}
|
|
219
|
+
error={error}
|
|
220
|
+
helperText={helperText}
|
|
221
|
+
onChange={this.onChange}
|
|
222
|
+
onBlur={this.onBlur}
|
|
223
|
+
onKeyPress={e => {
|
|
224
|
+
// once the Enter key is pressed, we force input blur
|
|
225
|
+
if (e.key === 'Enter' && this.inputRef) {
|
|
226
|
+
this.inputRef.blur();
|
|
227
|
+
}
|
|
228
|
+
}}
|
|
229
|
+
onKeyDown={e => {
|
|
230
|
+
if (e.key === 'ArrowUp') {
|
|
231
|
+
this.changeValue(e);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (e.key === 'ArrowDown') {
|
|
235
|
+
this.changeValue(e, -1);
|
|
236
|
+
}
|
|
237
|
+
}}
|
|
238
|
+
type="number"
|
|
239
|
+
className={names}
|
|
240
|
+
InputProps={{
|
|
241
|
+
className: inputClassName,
|
|
242
|
+
disableUnderline: disableUnderline,
|
|
243
|
+
startAdornment: (
|
|
244
|
+
<InputAdornment position="start">
|
|
245
|
+
<IconButton
|
|
246
|
+
className={classes.iconButton}
|
|
247
|
+
disabled={disabled}
|
|
248
|
+
onClick={e => this.changeValue(e, -1, true)}
|
|
249
|
+
>
|
|
250
|
+
<Remove fontSize="small" />
|
|
251
|
+
</IconButton>
|
|
252
|
+
</InputAdornment>
|
|
253
|
+
),
|
|
254
|
+
endAdornment: (
|
|
255
|
+
<InputAdornment position="end">
|
|
256
|
+
<IconButton
|
|
257
|
+
className={classes.iconButton}
|
|
258
|
+
disabled={disabled}
|
|
259
|
+
onClick={e => this.changeValue(e, 1, true)}
|
|
260
|
+
>
|
|
261
|
+
<Add fontSize="small" />
|
|
262
|
+
</IconButton>
|
|
263
|
+
</InputAdornment>
|
|
264
|
+
)
|
|
265
|
+
}}
|
|
266
|
+
inputProps={{
|
|
267
|
+
style: { textAlign },
|
|
268
|
+
min,
|
|
269
|
+
max
|
|
270
|
+
}}
|
|
271
|
+
/>
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export default withStyles(styles)(NumberTextFieldCustom);
|