@pie-lib/config-ui 10.10.4-next.62 → 10.10.4-next.626
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 +93 -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 +44 -48
- 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 +22 -2
- package/src/feedback-config/feedback-selector.jsx +1 -0
- 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.626+ec82d2a5",
|
|
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": "^
|
|
13
|
+
"@pie-lib/editable-html": "^9.1.4",
|
|
14
14
|
"@pie-lib/icons": "^2.4.25",
|
|
15
|
-
"@pie-lib/render-ui": "^4.
|
|
15
|
+
"@pie-lib/render-ui": "^4.13.4",
|
|
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": "ec82d2a52d750cb7e069157bc2c58dee83227ce0"
|
|
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;
|
|
@@ -25,8 +25,12 @@ const EditableHtmlContainer = withStyles(theme => ({
|
|
|
25
25
|
className,
|
|
26
26
|
imageSupport,
|
|
27
27
|
disabled,
|
|
28
|
+
spellCheck,
|
|
28
29
|
nonEmpty,
|
|
29
|
-
toolbarOpts
|
|
30
|
+
toolbarOpts,
|
|
31
|
+
error,
|
|
32
|
+
maxImageWidth,
|
|
33
|
+
maxImageHeight
|
|
30
34
|
}) => {
|
|
31
35
|
const names = classNames(classes.labelContainer, className);
|
|
32
36
|
|
|
@@ -36,11 +40,16 @@ 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}
|
|
52
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
44
53
|
/>
|
|
45
54
|
</div>
|
|
46
55
|
</InputContainer>
|
|
@@ -183,10 +192,13 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
183
192
|
useLetterOrdering,
|
|
184
193
|
imageSupport,
|
|
185
194
|
disabled,
|
|
195
|
+
spellCheck,
|
|
186
196
|
nonEmpty,
|
|
187
197
|
allowFeedBack,
|
|
188
198
|
allowDelete,
|
|
189
|
-
toolbarOpts
|
|
199
|
+
toolbarOpts,
|
|
200
|
+
error,
|
|
201
|
+
noCorrectAnswerError
|
|
190
202
|
} = this.props;
|
|
191
203
|
|
|
192
204
|
const InputToggle = mode === 'checkbox' ? InputCheckbox : InputRadio;
|
|
@@ -204,6 +216,7 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
204
216
|
onChange={this.onCheckedChange}
|
|
205
217
|
label={!noLabels ? 'Correct' : ''}
|
|
206
218
|
checked={!!data.correct}
|
|
219
|
+
error={noCorrectAnswerError}
|
|
207
220
|
/>
|
|
208
221
|
<div className={classes.middleColumn}>
|
|
209
222
|
<EditableHtmlContainer
|
|
@@ -212,9 +225,12 @@ export class ChoiceConfiguration extends React.Component {
|
|
|
212
225
|
onChange={this.onLabelChange}
|
|
213
226
|
imageSupport={imageSupport}
|
|
214
227
|
disabled={disabled}
|
|
228
|
+
spellCheck={spellCheck}
|
|
215
229
|
nonEmpty={nonEmpty}
|
|
216
230
|
toolbarOpts={toolbarOpts}
|
|
231
|
+
error={error}
|
|
217
232
|
/>
|
|
233
|
+
{error && <div className={classes.errorText}>{error}</div>}
|
|
218
234
|
|
|
219
235
|
{allowFeedBack && (
|
|
220
236
|
<Feedback
|
|
@@ -294,6 +310,10 @@ const styles = theme => ({
|
|
|
294
310
|
display: 'flex',
|
|
295
311
|
flex: 1,
|
|
296
312
|
flexDirection: 'column'
|
|
313
|
+
},
|
|
314
|
+
errorText: {
|
|
315
|
+
fontSize: '12px',
|
|
316
|
+
color: 'red'
|
|
297
317
|
}
|
|
298
318
|
});
|
|
299
319
|
|
|
@@ -102,6 +102,7 @@ export class FeedbackSelector extends React.Component {
|
|
|
102
102
|
onChange={this.changeCustom}
|
|
103
103
|
markup={feedback.custom || ''}
|
|
104
104
|
toolbarOpts={toolbarOpts}
|
|
105
|
+
languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
|
|
105
106
|
/>
|
|
106
107
|
</div>
|
|
107
108
|
)}
|
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);
|