@pie-lib/config-ui 10.10.4-next.62 → 10.10.4-next.630

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 +97 -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 +26 -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.62+1f1d2cba",
3
+ "version": "10.10.4-next.630+b5e67e19",
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.62+1f1d2cba",
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": "1f1d2cba382179d4a5e3956f5763ae0db8882bde"
29
+ "gitHead": "b5e67e1942ad8de77f6810869a0ebcd930cdbc18"
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,13 @@ 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,
34
+ uploadSoundSupport
30
35
  }) => {
31
36
  const names = classNames(classes.labelContainer, className);
32
37
 
@@ -36,11 +41,17 @@ const EditableHtmlContainer = withStyles(theme => ({
36
41
  <EditableHtml
37
42
  markup={value || ''}
38
43
  disabled={disabled}
44
+ spellCheck={spellCheck}
39
45
  nonEmpty={nonEmpty}
40
46
  onChange={onChange}
41
47
  imageSupport={imageSupport}
42
48
  className={classes.editor}
43
49
  toolbarOpts={toolbarOpts}
50
+ error={error}
51
+ maxImageWidth={maxImageWidth}
52
+ maxImageHeight={maxImageHeight}
53
+ uploadSoundSupport={uploadSoundSupport}
54
+ languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
44
55
  />
45
56
  </div>
46
57
  </InputContainer>
@@ -183,10 +194,14 @@ export class ChoiceConfiguration extends React.Component {
183
194
  useLetterOrdering,
184
195
  imageSupport,
185
196
  disabled,
197
+ spellCheck,
186
198
  nonEmpty,
187
199
  allowFeedBack,
188
200
  allowDelete,
189
- toolbarOpts
201
+ toolbarOpts,
202
+ error,
203
+ noCorrectAnswerError,
204
+ uploadSoundSupport
190
205
  } = this.props;
191
206
 
192
207
  const InputToggle = mode === 'checkbox' ? InputCheckbox : InputRadio;
@@ -204,6 +219,7 @@ export class ChoiceConfiguration extends React.Component {
204
219
  onChange={this.onCheckedChange}
205
220
  label={!noLabels ? 'Correct' : ''}
206
221
  checked={!!data.correct}
222
+ error={noCorrectAnswerError}
207
223
  />
208
224
  <div className={classes.middleColumn}>
209
225
  <EditableHtmlContainer
@@ -212,9 +228,13 @@ export class ChoiceConfiguration extends React.Component {
212
228
  onChange={this.onLabelChange}
213
229
  imageSupport={imageSupport}
214
230
  disabled={disabled}
231
+ spellCheck={spellCheck}
215
232
  nonEmpty={nonEmpty}
216
233
  toolbarOpts={toolbarOpts}
234
+ error={error}
235
+ uploadSoundSupport={uploadSoundSupport}
217
236
  />
237
+ {error && <div className={classes.errorText}>{error}</div>}
218
238
 
219
239
  {allowFeedBack && (
220
240
  <Feedback
@@ -294,6 +314,10 @@ const styles = theme => ({
294
314
  display: 'flex',
295
315
  flex: 1,
296
316
  flexDirection: 'column'
317
+ },
318
+ errorText: {
319
+ fontSize: '12px',
320
+ color: 'red'
297
321
  }
298
322
  });
299
323
 
@@ -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);