@pie-lib/config-ui 10.10.4-next.59 → 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.
Files changed (71) hide show
  1. package/CHANGELOG.md +346 -0
  2. package/lib/alert-dialog.js +44 -0
  3. package/lib/alert-dialog.js.map +1 -0
  4. package/lib/checkbox.js +4 -4
  5. package/lib/checkbox.js.map +1 -1
  6. package/lib/choice-configuration/feedback-menu.js +41 -53
  7. package/lib/choice-configuration/feedback-menu.js.map +1 -1
  8. package/lib/choice-configuration/index.js +93 -81
  9. package/lib/choice-configuration/index.js.map +1 -1
  10. package/lib/choice-utils.js +8 -8
  11. package/lib/choice-utils.js.map +1 -1
  12. package/lib/feedback-config/feedback-selector.js +44 -48
  13. package/lib/feedback-config/feedback-selector.js.map +1 -1
  14. package/lib/feedback-config/group.js +5 -5
  15. package/lib/feedback-config/group.js.map +1 -1
  16. package/lib/feedback-config/index.js +46 -52
  17. package/lib/feedback-config/index.js.map +1 -1
  18. package/lib/form-section.js +8 -6
  19. package/lib/form-section.js.map +1 -1
  20. package/lib/help.js +30 -37
  21. package/lib/help.js.map +1 -1
  22. package/lib/index.js +66 -45
  23. package/lib/index.js.map +1 -1
  24. package/lib/input.js +35 -40
  25. package/lib/input.js.map +1 -1
  26. package/lib/inputs.js +28 -17
  27. package/lib/inputs.js.map +1 -1
  28. package/lib/langs.js +37 -45
  29. package/lib/langs.js.map +1 -1
  30. package/lib/layout/config-layout.js +29 -37
  31. package/lib/layout/config-layout.js.map +1 -1
  32. package/lib/layout/index.js +2 -2
  33. package/lib/layout/index.js.map +1 -1
  34. package/lib/layout/layout-contents.js +28 -34
  35. package/lib/layout/layout-contents.js.map +1 -1
  36. package/lib/layout/settings-box.js +23 -31
  37. package/lib/layout/settings-box.js.map +1 -1
  38. package/lib/mui-box/index.js +3 -3
  39. package/lib/mui-box/index.js.map +1 -1
  40. package/lib/number-text-field-custom.js +364 -0
  41. package/lib/number-text-field-custom.js.map +1 -0
  42. package/lib/number-text-field.js +33 -42
  43. package/lib/number-text-field.js.map +1 -1
  44. package/lib/radio-with-label.js +4 -4
  45. package/lib/radio-with-label.js.map +1 -1
  46. package/lib/settings/display-size.js +10 -10
  47. package/lib/settings/display-size.js.map +1 -1
  48. package/lib/settings/index.js +11 -17
  49. package/lib/settings/index.js.map +1 -1
  50. package/lib/settings/panel.js +58 -68
  51. package/lib/settings/panel.js.map +1 -1
  52. package/lib/settings/settings-radio-label.js +4 -4
  53. package/lib/settings/settings-radio-label.js.map +1 -1
  54. package/lib/settings/toggle.js +5 -5
  55. package/lib/settings/toggle.js.map +1 -1
  56. package/lib/tabs/index.js +28 -35
  57. package/lib/tabs/index.js.map +1 -1
  58. package/lib/tags-input/index.js +32 -40
  59. package/lib/tags-input/index.js.map +1 -1
  60. package/lib/two-choice.js +38 -48
  61. package/lib/two-choice.js.map +1 -1
  62. package/lib/with-stateful-model.js +23 -30
  63. package/lib/with-stateful-model.js.map +1 -1
  64. package/package.json +4 -4
  65. package/src/alert-dialog.jsx +43 -0
  66. package/src/choice-configuration/index.jsx +22 -2
  67. package/src/feedback-config/feedback-selector.jsx +1 -0
  68. package/src/form-section.jsx +2 -2
  69. package/src/index.js +4 -0
  70. package/src/inputs.jsx +13 -5
  71. 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 _react = _interopRequireDefault(require("react"));
9
-
10
- var _propTypes = _interopRequireDefault(require("prop-types"));
10
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
11
11
 
12
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
12
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
13
13
 
14
- function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
14
+ var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
15
15
 
16
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
17
17
 
18
- function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
18
+ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
19
19
 
20
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
20
+ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
21
21
 
22
- function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
22
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
23
23
 
24
- function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
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
- function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
26
+ var _propTypes = _interopRequireDefault(require("prop-types"));
29
27
 
30
- function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
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 _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
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
- /*#__PURE__*/
37
- function (_React$Component) {
38
- _inherits(Stateful, _React$Component);
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
- _classCallCheck(this, Stateful);
44
-
45
- _this = _possibleConstructorReturn(this, _getPrototypeOf(Stateful).call(this, props));
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
- _createClass(Stateful, [{
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
- _defineProperty(Stateful, "propTypes", {
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,"sources":["../src/with-stateful-model.jsx"],"names":["withStatefulModel","Component","Stateful","props","model","setState","onChange","state","React","PropTypes","object","isRequired","func"],"mappings":";;;;;;;AAAA;;AACA;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAMA,iBAAiB,GAAG,SAApBA,iBAAoB,CAAAC,SAAS,EAAI;AAAA,MAC/BC,QAD+B;AAAA;AAAA;AAAA;;AAOnC,sBAAYC,KAAZ,EAAmB;AAAA;;AAAA;;AACjB,oFAAMA,KAAN;;AADiB,iEAWR,UAAAC,KAAK,EAAI;AAClB,cAAKC,QAAL,CAAc;AAAED,UAAAA,KAAK,EAALA;AAAF,SAAd,EAAyB,YAAM;AAC7B,gBAAKD,KAAL,CAAWG,QAAX,CAAoB,MAAKC,KAAL,CAAWH,KAA/B;AACD,SAFD;AAGD,OAfkB;;AAEjB,YAAKG,KAAL,GAAa;AACXH,QAAAA,KAAK,EAAED,KAAK,CAACC;AADF,OAAb;AAFiB;AAKlB;;AAZkC;AAAA;AAAA,gDAcTD,KAdS,EAcF;AAC/B,aAAKE,QAAL,CAAc;AAAED,UAAAA,KAAK,EAAED,KAAK,CAACC;AAAf,SAAd;AACD;AAhBkC;AAAA;AAAA,+BAwB1B;AACP,eAAO,gCAAC,SAAD;AAAW,UAAA,KAAK,EAAE,KAAKG,KAAL,CAAWH,KAA7B;AAAoC,UAAA,QAAQ,EAAE,KAAKE;AAAnD,UAAP;AACD;AA1BkC;;AAAA;AAAA,IACdE,kBAAMP,SADQ;;AAAA,kBAC/BC,QAD+B,eAEhB;AACjBE,IAAAA,KAAK,EAAEK,sBAAUC,MAAV,CAAiBC,UADP;AAEjBL,IAAAA,QAAQ,EAAEG,sBAAUG,IAAV,CAAeD;AAFR,GAFgB;;AA6BrC,SAAOT,QAAP;AACD,CA9BD;;eAgCeF,iB","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"],"file":"with-stateful-model.js"}
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.59+8e5ab060",
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": "^7.17.4-next.59+8e5ab060",
13
+ "@pie-lib/editable-html": "^9.1.4",
14
14
  "@pie-lib/icons": "^2.4.25",
15
- "@pie-lib/render-ui": "^4.12.0",
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": "8e5ab060783241f43cb33a737f5c6db8032ca533"
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
  )}
@@ -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);