@pie-lib/config-ui 11.9.24 → 11.11.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/NEXT.CHANGELOG.json +1 -0
  3. package/lib/__tests__/choice-utils.test.js +16 -0
  4. package/lib/__tests__/langs.test.js +55 -0
  5. package/lib/__tests__/number-text-field.test.js +128 -0
  6. package/lib/__tests__/settings-panel.test.js +201 -0
  7. package/lib/__tests__/two-choice.test.js +33 -0
  8. package/lib/alert-dialog.js +39 -8
  9. package/lib/checkbox.js +7 -2
  10. package/lib/choice-configuration/__tests__/feedback-menu.test.js +20 -0
  11. package/lib/choice-configuration/__tests__/index.test.js +119 -0
  12. package/lib/choice-configuration/feedback-menu.js +1 -1
  13. package/lib/choice-configuration/index.js +20 -9
  14. package/lib/choice-utils.js +1 -1
  15. package/lib/feedback-config/__tests__/feedback-config.test.js +78 -0
  16. package/lib/feedback-config/__tests__/feedback-selector.test.js +71 -0
  17. package/lib/feedback-config/feedback-selector.js +1 -1
  18. package/lib/feedback-config/group.js +1 -1
  19. package/lib/feedback-config/index.js +1 -1
  20. package/lib/form-section.js +1 -1
  21. package/lib/help.js +1 -1
  22. package/lib/index.js +1 -1
  23. package/lib/input.js +1 -1
  24. package/lib/inputs.js +9 -3
  25. package/lib/langs.js +1 -1
  26. package/lib/layout/__tests__/config.layout.test.js +33 -0
  27. package/lib/layout/__tests__/layout-content.test.js +6 -0
  28. package/lib/layout/config-layout.js +28 -11
  29. package/lib/layout/index.js +1 -1
  30. package/lib/layout/layout-contents.js +1 -1
  31. package/lib/layout/settings-box.js +1 -1
  32. package/lib/mui-box/index.js +1 -1
  33. package/lib/number-text-field-custom.js +135 -44
  34. package/lib/number-text-field.js +18 -19
  35. package/lib/radio-with-label.js +10 -2
  36. package/lib/settings/display-size.js +1 -1
  37. package/lib/settings/index.js +4 -2
  38. package/lib/settings/panel.js +8 -5
  39. package/lib/settings/settings-radio-label.js +10 -2
  40. package/lib/settings/toggle.js +19 -1
  41. package/lib/tabs/index.js +1 -1
  42. package/lib/tags-input/__tests__/index.test.js +88 -0
  43. package/lib/tags-input/index.js +1 -1
  44. package/lib/two-choice.js +1 -1
  45. package/lib/with-stateful-model.js +1 -1
  46. package/package.json +5 -5
  47. package/src/__tests__/__snapshots__/langs.test.jsx.snap +32 -0
  48. package/src/__tests__/__snapshots__/settings-panel.test.js.snap +115 -0
  49. package/src/__tests__/__snapshots__/two-choice.test.js.snap +171 -0
  50. package/src/__tests__/choice-utils.test.js +12 -0
  51. package/src/__tests__/langs.test.jsx +37 -0
  52. package/src/__tests__/number-text-field.test.jsx +148 -0
  53. package/src/__tests__/settings-panel.test.js +204 -0
  54. package/src/__tests__/two-choice.test.js +24 -0
  55. package/src/alert-dialog.jsx +27 -7
  56. package/src/checkbox.jsx +12 -1
  57. package/src/choice-configuration/__tests__/__snapshots__/feedback-menu.test.jsx.snap +51 -0
  58. package/src/choice-configuration/__tests__/__snapshots__/index.test.jsx.snap +519 -0
  59. package/src/choice-configuration/__tests__/feedback-menu.test.jsx +10 -0
  60. package/src/choice-configuration/__tests__/index.test.jsx +92 -0
  61. package/src/choice-configuration/index.jsx +14 -3
  62. package/src/feedback-config/__tests__/__snapshots__/feedback-config.test.jsx.snap +27 -0
  63. package/src/feedback-config/__tests__/__snapshots__/feedback-selector.test.jsx.snap +38 -0
  64. package/src/feedback-config/__tests__/feedback-config.test.jsx +71 -0
  65. package/src/feedback-config/__tests__/feedback-selector.test.jsx +60 -0
  66. package/src/feedback-config/feedback-selector.jsx +0 -0
  67. package/src/inputs.jsx +9 -2
  68. package/src/layout/__tests__/__snapshots__/config.layout.test.jsx.snap +59 -0
  69. package/src/layout/__tests__/config.layout.test.jsx +42 -0
  70. package/src/layout/__tests__/layout-content.test.jsx +3 -0
  71. package/src/layout/config-layout.jsx +16 -8
  72. package/src/number-text-field-custom.jsx +86 -28
  73. package/src/number-text-field.jsx +6 -5
  74. package/src/radio-with-label.jsx +12 -2
  75. package/src/settings/index.js +2 -1
  76. package/src/settings/panel.jsx +5 -2
  77. package/src/settings/settings-radio-label.jsx +12 -2
  78. package/src/settings/toggle.jsx +20 -2
  79. package/src/tags-input/__tests__/__snapshots__/index.test.jsx.snap +170 -0
  80. package/src/tags-input/__tests__/index.test.jsx +62 -0
  81. package/README.md +0 -12
  82. package/lib/alert-dialog.js.map +0 -1
  83. package/lib/checkbox.js.map +0 -1
  84. package/lib/choice-configuration/feedback-menu.js.map +0 -1
  85. package/lib/choice-configuration/index.js.map +0 -1
  86. package/lib/choice-utils.js.map +0 -1
  87. package/lib/feedback-config/feedback-selector.js.map +0 -1
  88. package/lib/feedback-config/group.js.map +0 -1
  89. package/lib/feedback-config/index.js.map +0 -1
  90. package/lib/form-section.js.map +0 -1
  91. package/lib/help.js.map +0 -1
  92. package/lib/index.js.map +0 -1
  93. package/lib/input.js.map +0 -1
  94. package/lib/inputs.js.map +0 -1
  95. package/lib/langs.js.map +0 -1
  96. package/lib/layout/config-layout.js.map +0 -1
  97. package/lib/layout/index.js.map +0 -1
  98. package/lib/layout/layout-contents.js.map +0 -1
  99. package/lib/layout/settings-box.js.map +0 -1
  100. package/lib/mui-box/index.js.map +0 -1
  101. package/lib/number-text-field-custom.js.map +0 -1
  102. package/lib/number-text-field.js.map +0 -1
  103. package/lib/radio-with-label.js.map +0 -1
  104. package/lib/settings/display-size.js.map +0 -1
  105. package/lib/settings/index.js.map +0 -1
  106. package/lib/settings/panel.js.map +0 -1
  107. package/lib/settings/settings-radio-label.js.map +0 -1
  108. package/lib/settings/toggle.js.map +0 -1
  109. package/lib/tabs/index.js.map +0 -1
  110. package/lib/tags-input/index.js.map +0 -1
  111. package/lib/two-choice.js.map +0 -1
  112. package/lib/with-stateful-model.js.map +0 -1
@@ -8,6 +8,7 @@ import IconButton from '@material-ui/core/IconButton';
8
8
  import InputAdornment from '@material-ui/core/InputAdornment';
9
9
  import Remove from '@material-ui/icons/Remove';
10
10
  import Add from '@material-ui/icons/Add';
11
+ import * as math from 'mathjs';
11
12
 
12
13
  const styles = () => ({
13
14
  input: {
@@ -53,7 +54,7 @@ export class NumberTextFieldCustom extends React.Component {
53
54
  helperText: PropTypes.string,
54
55
  onChange: PropTypes.func.isRequired,
55
56
  onlyIntegersAllowed: PropTypes.bool,
56
- value: PropTypes.number,
57
+ value: PropTypes.any,
57
58
  min: PropTypes.number,
58
59
  max: PropTypes.number,
59
60
  step: PropTypes.number,
@@ -61,6 +62,7 @@ export class NumberTextFieldCustom extends React.Component {
61
62
  disableUnderline: PropTypes.bool,
62
63
  textAlign: PropTypes.string,
63
64
  variant: PropTypes.string,
65
+ type: PropTypes.string,
64
66
  };
65
67
 
66
68
  static defaultProps = {
@@ -89,13 +91,13 @@ export class NumberTextFieldCustom extends React.Component {
89
91
  }
90
92
 
91
93
  UNSAFE_componentWillReceiveProps(props) {
92
- const { value, currentIndex } = this.normalizeValueAndIndex(props.customValues, props.value);
94
+ const { value, currentIndex } = this.normalizeValueAndIndex(props.customValues, props.value, props.min, props.max);
93
95
 
94
96
  this.setState({ value, currentIndex });
95
97
  }
96
98
 
97
- clamp(value) {
98
- const { min, max, customValues } = this.props;
99
+ clamp(value, min = this.props.min, max = this.props.max) {
100
+ const { customValues } = this.props;
99
101
 
100
102
  if ((customValues || []).length > 0) {
101
103
  return value;
@@ -116,12 +118,14 @@ export class NumberTextFieldCustom extends React.Component {
116
118
  return value;
117
119
  }
118
120
 
119
- normalizeValueAndIndex = (customValues, number) => {
120
- const value = this.clamp(number);
121
+ normalizeValueAndIndex = (customValues, number, min, max) => {
122
+ const { type } = this.props;
123
+ const value = this.clamp(number, min, max);
121
124
  const currentIndex = (customValues || []).findIndex((val) => val === value);
122
125
 
123
126
  if ((customValues || []).length > 0 && currentIndex === -1) {
124
- const closestValue = this.getClosestValue(customValues, value);
127
+ const closestValue =
128
+ type === 'text' ? this.getClosestFractionValue(customValues, value) : this.getClosestValue(customValues, value);
125
129
 
126
130
  return { value: closestValue.value, currentIndex: closestValue.index };
127
131
  }
@@ -136,50 +140,92 @@ export class NumberTextFieldCustom extends React.Component {
136
140
  { value: customValues[0], index: 0 },
137
141
  );
138
142
 
139
- onBlur = (event) => {
140
- const { customValues, onlyIntegersAllowed } = this.props;
141
- const { value } = event.target;
142
- const rawNumber = onlyIntegersAllowed ? parseInt(value) : parseFloat(value);
143
+ getClosestFractionValue = (customValues, number) =>
144
+ customValues.reduce(
145
+ (closest, value, index) =>
146
+ Math.abs(math.number(math.fraction(value)) - math.number(math.fraction(number))) <
147
+ Math.abs(math.number(math.fraction(closest.value)) - math.number(math.fraction(number)))
148
+ ? { value, index }
149
+ : closest,
150
+ { value: customValues[0], index: 0 },
151
+ );
143
152
 
144
- const { value: number, currentIndex } = this.normalizeValueAndIndex(customValues, rawNumber);
153
+ getValidFraction = (value) => {
154
+ if (this.isPositiveInteger(value.trim())) {
155
+ return value.trim();
156
+ }
157
+ if (value.trim() === '' || value.trim().split('/').length !== 2) {
158
+ return false;
159
+ }
160
+ let [numerator, denominator] = value.trim().split('/');
161
+ if (isNaN(numerator) || isNaN(denominator)) {
162
+ return false;
163
+ }
164
+ numerator = parseFloat(numerator);
165
+ denominator = parseFloat(denominator);
166
+ if (!Number.isInteger(numerator) || !Number.isInteger(denominator)) {
167
+ return false;
168
+ }
169
+ if (numerator < 0 || denominator < 1) {
170
+ return false;
171
+ }
172
+ return numerator + '/' + denominator;
173
+ };
174
+
175
+ isPositiveInteger = (n) => {
176
+ return n >>> 0 === parseFloat(n);
177
+ };
145
178
 
146
- if (number !== this.state.value) {
147
- this.setState(
148
- {
149
- value: number.toString(),
150
- currentIndex,
151
- },
152
- () => this.props.onChange(event, number),
153
- );
179
+ onBlur = (event) => {
180
+ const { customValues, onlyIntegersAllowed, type } = this.props;
181
+ let { value } = event.target;
182
+ if (type === 'text') {
183
+ let tempValue = this.getValidFraction(value);
184
+ if (tempValue) {
185
+ value = tempValue;
186
+ } else {
187
+ value = this.props.value;
188
+ }
189
+ }
190
+ let rawNumber = onlyIntegersAllowed ? Math.round(parseFloat(value)) : parseFloat(value);
191
+ if (type === 'text') {
192
+ rawNumber = value.trim();
154
193
  }
194
+ const { value: number, currentIndex } = this.normalizeValueAndIndex(customValues, rawNumber);
195
+ this.setState(
196
+ {
197
+ value: number.toString(),
198
+ currentIndex,
199
+ },
200
+ () => this.props.onChange(event, number),
201
+ );
155
202
  };
156
203
 
157
204
  onChange(event) {
205
+ const { type } = this.props;
158
206
  const { value } = event.target;
159
-
207
+ if (type !== 'text' && typeof value === 'string' && value.trim() === '') {
208
+ return;
209
+ }
160
210
  this.setState({ value });
161
211
  }
162
212
 
163
213
  changeValue(event, sign = 1, shouldUpdate = false) {
164
214
  event.preventDefault();
165
-
166
215
  const { customValues, step, onlyIntegersAllowed, onChange } = this.props;
167
216
  const { currentIndex, value } = this.state;
168
217
  const updatedIndex = currentIndex + sign * 1;
169
218
  let number;
170
-
171
219
  if (customValues.length > 0) {
172
220
  if (updatedIndex < 0 || updatedIndex >= customValues.length) {
173
221
  return;
174
222
  }
175
-
176
223
  number = customValues[updatedIndex];
177
224
  } else {
178
225
  const rawNumber = onlyIntegersAllowed ? parseInt(value) : parseFloat(value);
179
226
  const updatedValue = (rawNumber * 10000 + step * sign * 10000) / 10000;
180
227
  number = this.clamp(updatedValue);
181
228
  }
182
-
183
229
  this.setState(
184
230
  {
185
231
  value: number.toString(),
@@ -202,14 +248,26 @@ export class NumberTextFieldCustom extends React.Component {
202
248
  error,
203
249
  min,
204
250
  max,
251
+ customValues,
205
252
  inputClassName,
206
253
  disableUnderline,
207
254
  helperText,
208
255
  variant,
209
256
  textAlign,
257
+ type = 'number',
210
258
  } = this.props;
211
259
  const { value } = this.state;
212
260
  const names = classNames(className, classes.input);
261
+ //Logic to disable the increment and decrement buttons
262
+ let disabledStart = false;
263
+ let disabledEnd = false;
264
+ if (customValues.length > 0) {
265
+ disabledStart = value === customValues[0];
266
+ disabledEnd = value === customValues[customValues.length - 1];
267
+ } else if (isFinite(min) && isFinite(max)) {
268
+ disabledStart = value === min;
269
+ disabledEnd = value === max;
270
+ }
213
271
 
214
272
  return (
215
273
  <TextField
@@ -238,7 +296,7 @@ export class NumberTextFieldCustom extends React.Component {
238
296
  }
239
297
  }}
240
298
  title={''}
241
- type="number"
299
+ type={type}
242
300
  className={names}
243
301
  InputProps={{
244
302
  className: inputClassName,
@@ -247,7 +305,7 @@ export class NumberTextFieldCustom extends React.Component {
247
305
  <InputAdornment position="start">
248
306
  <IconButton
249
307
  className={classes.iconButton}
250
- disabled={disabled}
308
+ disabled={disabled ? disabled : disabledStart}
251
309
  onClick={(e) => this.changeValue(e, -1, true)}
252
310
  >
253
311
  <Remove fontSize="small" />
@@ -258,7 +316,7 @@ export class NumberTextFieldCustom extends React.Component {
258
316
  <InputAdornment position="end">
259
317
  <IconButton
260
318
  className={classes.iconButton}
261
- disabled={disabled}
319
+ disabled={disabled ? disabled : disabledEnd}
262
320
  onClick={(e) => this.changeValue(e, 1, true)}
263
321
  >
264
322
  <Add fontSize="small" />
@@ -68,23 +68,24 @@ export class NumberTextField extends React.Component {
68
68
  }
69
69
 
70
70
  UNSAFE_componentWillReceiveProps(props) {
71
- const value = this.clamp(props.value);
71
+ const value = this.clamp(props.value, props.min, props.max);
72
+
72
73
  this.setState({ value });
73
74
  }
74
75
 
75
- clamp(value) {
76
+ clamp(value, min = this.props.min, max = this.props.max) {
76
77
  if (!isFinite(value)) {
77
- return fallbackNumber(this.props.min, this.props.max);
78
+ return fallbackNumber(min, max);
78
79
  }
79
80
 
80
- const { min, max } = this.props;
81
-
82
81
  if (isFinite(max)) {
83
82
  value = Math.min(value, max);
84
83
  }
84
+
85
85
  if (isFinite(min)) {
86
86
  value = Math.max(value, min);
87
87
  }
88
+
88
89
  return value;
89
90
  }
90
91
 
@@ -2,17 +2,27 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
2
2
  import Radio from '@material-ui/core/Radio';
3
3
  import React from 'react';
4
4
  import { withStyles } from '@material-ui/core/styles';
5
+ import { color } from "@pie-lib/render-ui"
5
6
 
6
7
  export default withStyles({
7
8
  label: {
8
9
  left: '-5px',
9
10
  position: 'relative',
10
11
  },
12
+ customColor: {
13
+ color: `${color.tertiary()} !important`
14
+ },
11
15
  })(({ label, value, checked, onChange, classes }) => (
12
16
  <FormControlLabel
13
17
  value={value}
14
- classes={classes}
15
- control={<Radio checked={checked} onChange={onChange} />}
18
+ classes={{ label: classes.label }}
19
+ control={
20
+ <Radio
21
+ className={classes.customColor}
22
+ checked={checked}
23
+ onChange={onChange}
24
+ />
25
+ }
16
26
  label={label}
17
27
  />
18
28
  ));
@@ -8,10 +8,11 @@ export const textField = (label, isConfigProperty = true) => ({
8
8
  isConfigProperty,
9
9
  });
10
10
 
11
- export const toggle = (label, isConfigProperty = false) => ({
11
+ export const toggle = (label, isConfigProperty = false, disabled = false) => ({
12
12
  type: 'toggle',
13
13
  label,
14
14
  isConfigProperty,
15
+ disabled,
15
16
  });
16
17
 
17
18
  const toChoice = (opt) => {
@@ -11,7 +11,7 @@ import debug from 'debug';
11
11
  import Toggle from './toggle';
12
12
  import { NChoice } from '../two-choice';
13
13
  import SettingsRadioLabel from './settings-radio-label';
14
- import { NumberTextField } from '../index';
14
+ import NumberTextField from '../number-text-field';
15
15
  import Checkbox from '../checkbox';
16
16
  import Typography from '@material-ui/core/Typography';
17
17
 
@@ -151,6 +151,7 @@ const NumberField = withStyles((theme) => ({
151
151
  showErrorWhenOutsideRange
152
152
  inputClassName={classes.wrapper}
153
153
  disableUnderline
154
+ classes={classes}
154
155
  />
155
156
  );
156
157
  });
@@ -168,7 +169,9 @@ TextField.propTypes = {
168
169
  ...baseTypes,
169
170
  };
170
171
 
171
- const ToggleWrapper = ({ label, value, onChange }) => <Toggle label={label} checked={!!value} toggle={onChange} />;
172
+ const ToggleWrapper = ({ disabled, label, value, onChange }) => (
173
+ <Toggle label={label} checked={!!value} disabled={!!disabled} toggle={onChange} />
174
+ );
172
175
 
173
176
  ToggleWrapper.propTypes = { ...baseTypes, value: PropTypes.bool };
174
177
 
@@ -2,6 +2,7 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
2
2
  import Radio from '@material-ui/core/Radio';
3
3
  import React from 'react';
4
4
  import { withStyles } from '@material-ui/core/styles';
5
+ import { color } from '@pie-lib/render-ui';
5
6
 
6
7
  export default withStyles((theme) => ({
7
8
  label: {
@@ -10,11 +11,20 @@ export default withStyles((theme) => ({
10
11
  left: '-5px',
11
12
  position: 'relative',
12
13
  },
14
+ customColor: {
15
+ color: `${color.tertiary()} !important`
16
+ },
13
17
  }))(({ label, value, checked, onChange, classes }) => (
14
18
  <FormControlLabel
15
19
  value={value}
16
- classes={classes}
17
- control={<Radio checked={checked} onChange={onChange} />}
20
+ classes={{ label: classes.label }}
21
+ control={
22
+ <Radio
23
+ className={classes.customColor}
24
+ checked={checked}
25
+ onChange={onChange}
26
+ />
27
+ }
18
28
  label={label}
19
29
  />
20
30
  ));
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
3
3
  import InputLabel from '@material-ui/core/InputLabel';
4
4
  import { withStyles } from '@material-ui/core/styles';
5
5
  import Switch from '@material-ui/core/Switch';
6
+ import classNames from 'classnames';
7
+ import { color } from '@pie-lib/render-ui';
6
8
 
7
9
  const Toggle = withStyles((theme) => ({
8
10
  toggle: {
@@ -15,10 +17,26 @@ const Toggle = withStyles((theme) => ({
15
17
  fontSize: theme.typography.fontSize,
16
18
  paddingTop: theme.spacing.unit * 2,
17
19
  },
18
- }))(({ checked, label, toggle, classes }) => (
20
+ checkedThumb: {
21
+ color: `${color.tertiary()} !important`,
22
+ },
23
+ checkedBar: {
24
+ backgroundColor: `${color.tertiaryLight()} !important`,
25
+ },
26
+ }))(({ checked, disabled, label, toggle, classes }) => (
19
27
  <div className={classes.toggle}>
20
28
  <InputLabel className={classes.label}>{label}</InputLabel>
21
- <Switch checked={checked} onChange={(e) => toggle(e.target.checked)} />
29
+ <Switch
30
+ classes={{
31
+ checked: classNames(classes.checkedThumb),
32
+ bar: classNames({
33
+ [classes.checkedBar]: checked,
34
+ }),
35
+ }}
36
+ checked={checked}
37
+ disabled={disabled}
38
+ onChange={(e) => toggle(e.target.checked)}
39
+ />
22
40
  </div>
23
41
  ));
24
42
 
@@ -0,0 +1,170 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TagsInput snapshots renders 1`] = `
4
+ <TagsInput
5
+ classes={
6
+ Object {
7
+ "tagsInput": "tagsInput",
8
+ }
9
+ }
10
+ onChange={[MockFunction]}
11
+ tags={
12
+ Array [
13
+ "foo",
14
+ ]
15
+ }
16
+ >
17
+ <WithStyles(Component)
18
+ focused={false}
19
+ >
20
+ <Component
21
+ classes={
22
+ Object {
23
+ "focused": "Component-focused-2",
24
+ "muiBox": "Component-muiBox-1",
25
+ }
26
+ }
27
+ focused={false}
28
+ >
29
+ <div
30
+ className="Component-muiBox-1"
31
+ >
32
+ <div
33
+ className="tagsInput"
34
+ >
35
+ <WithStyles(Component)
36
+ key="0"
37
+ label="foo"
38
+ onDelete={[Function]}
39
+ >
40
+ <Component
41
+ classes={
42
+ Object {
43
+ "tag": "Component-tag-3",
44
+ }
45
+ }
46
+ label="foo"
47
+ onDelete={[Function]}
48
+ >
49
+ <WithStyles(Chip)
50
+ className="Component-tag-3"
51
+ label="foo"
52
+ onDelete={[Function]}
53
+ >
54
+ <Chip
55
+ className="Component-tag-3"
56
+ classes={
57
+ Object {
58
+ "avatar": "MuiChip-avatar-16",
59
+ "avatarChildren": "MuiChip-avatarChildren-19",
60
+ "avatarColorPrimary": "MuiChip-avatarColorPrimary-17",
61
+ "avatarColorSecondary": "MuiChip-avatarColorSecondary-18",
62
+ "clickable": "MuiChip-clickable-7",
63
+ "clickableColorPrimary": "MuiChip-clickableColorPrimary-8",
64
+ "clickableColorSecondary": "MuiChip-clickableColorSecondary-9",
65
+ "colorPrimary": "MuiChip-colorPrimary-5",
66
+ "colorSecondary": "MuiChip-colorSecondary-6",
67
+ "deletable": "MuiChip-deletable-10",
68
+ "deletableColorPrimary": "MuiChip-deletableColorPrimary-11",
69
+ "deletableColorSecondary": "MuiChip-deletableColorSecondary-12",
70
+ "deleteIcon": "MuiChip-deleteIcon-24",
71
+ "deleteIconColorPrimary": "MuiChip-deleteIconColorPrimary-25",
72
+ "deleteIconColorSecondary": "MuiChip-deleteIconColorSecondary-26",
73
+ "deleteIconOutlinedColorPrimary": "MuiChip-deleteIconOutlinedColorPrimary-27",
74
+ "deleteIconOutlinedColorSecondary": "MuiChip-deleteIconOutlinedColorSecondary-28",
75
+ "icon": "MuiChip-icon-20",
76
+ "iconColorPrimary": "MuiChip-iconColorPrimary-21",
77
+ "iconColorSecondary": "MuiChip-iconColorSecondary-22",
78
+ "label": "MuiChip-label-23",
79
+ "outlined": "MuiChip-outlined-13",
80
+ "outlinedPrimary": "MuiChip-outlinedPrimary-14",
81
+ "outlinedSecondary": "MuiChip-outlinedSecondary-15",
82
+ "root": "MuiChip-root-4",
83
+ }
84
+ }
85
+ color="default"
86
+ component="div"
87
+ label="foo"
88
+ onDelete={[Function]}
89
+ variant="default"
90
+ >
91
+ <div
92
+ className="MuiChip-root-4 MuiChip-deletable-10 Component-tag-3"
93
+ onKeyDown={[Function]}
94
+ onKeyUp={[Function]}
95
+ role="button"
96
+ tabIndex={0}
97
+ >
98
+ <span
99
+ className="MuiChip-label-23"
100
+ >
101
+ foo
102
+ </span>
103
+ <pure(Cancel)
104
+ className="MuiChip-deleteIcon-24"
105
+ onClick={[Function]}
106
+ >
107
+ <Cancel
108
+ className="MuiChip-deleteIcon-24"
109
+ onClick={[Function]}
110
+ >
111
+ <WithStyles(SvgIcon)
112
+ className="MuiChip-deleteIcon-24"
113
+ onClick={[Function]}
114
+ >
115
+ <SvgIcon
116
+ className="MuiChip-deleteIcon-24"
117
+ classes={
118
+ Object {
119
+ "colorAction": "MuiSvgIcon-colorAction-32",
120
+ "colorDisabled": "MuiSvgIcon-colorDisabled-34",
121
+ "colorError": "MuiSvgIcon-colorError-33",
122
+ "colorPrimary": "MuiSvgIcon-colorPrimary-30",
123
+ "colorSecondary": "MuiSvgIcon-colorSecondary-31",
124
+ "fontSizeInherit": "MuiSvgIcon-fontSizeInherit-35",
125
+ "fontSizeLarge": "MuiSvgIcon-fontSizeLarge-37",
126
+ "fontSizeSmall": "MuiSvgIcon-fontSizeSmall-36",
127
+ "root": "MuiSvgIcon-root-29",
128
+ }
129
+ }
130
+ color="inherit"
131
+ component="svg"
132
+ fontSize="default"
133
+ onClick={[Function]}
134
+ viewBox="0 0 24 24"
135
+ >
136
+ <svg
137
+ aria-hidden="true"
138
+ className="MuiSvgIcon-root-29 MuiChip-deleteIcon-24"
139
+ focusable="false"
140
+ onClick={[Function]}
141
+ role="presentation"
142
+ viewBox="0 0 24 24"
143
+ >
144
+ <path
145
+ d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"
146
+ />
147
+ </svg>
148
+ </SvgIcon>
149
+ </WithStyles(SvgIcon)>
150
+ </Cancel>
151
+ </pure(Cancel)>
152
+ </div>
153
+ </Chip>
154
+ </WithStyles(Chip)>
155
+ </Component>
156
+ </WithStyles(Component)>
157
+ <input
158
+ onBlur={[Function]}
159
+ onChange={[Function]}
160
+ onFocus={[Function]}
161
+ onKeyDown={[Function]}
162
+ type="text"
163
+ value=""
164
+ />
165
+ </div>
166
+ </div>
167
+ </Component>
168
+ </WithStyles(Component)>
169
+ </TagsInput>
170
+ `;
@@ -0,0 +1,62 @@
1
+ import { TagsInput } from '../index';
2
+ import toJson from 'enzyme-to-json';
3
+ import { shallow, mount } from 'enzyme';
4
+ import React from 'react';
5
+
6
+ describe('TagsInput', () => {
7
+ describe('snapshots', () => {
8
+ it('renders', () => {
9
+ const wrapper = mount(<TagsInput classes={{ tagsInput: 'tagsInput' }} tags={['foo']} onChange={jest.fn()} />);
10
+ expect(toJson(wrapper)).toMatchSnapshot();
11
+ });
12
+ });
13
+
14
+ describe('logic', () => {
15
+ let onChange;
16
+ const mkWrapper = () => {
17
+ onChange = jest.fn();
18
+ return shallow(<TagsInput onChange={onChange} classes={{}} tags={['foo']} />);
19
+ };
20
+
21
+ describe('onFocus', () => {
22
+ it('sets state.focused = true', () => {
23
+ const wrapper = mkWrapper();
24
+ wrapper.instance().onFocus();
25
+ expect(wrapper.state('focused')).toEqual(true);
26
+ });
27
+ });
28
+
29
+ describe('onBlur', () => {
30
+ it('sets state.focused = false', () => {
31
+ const wrapper = mkWrapper();
32
+ wrapper.instance().onFocus();
33
+ wrapper.instance().onBlur();
34
+ expect(wrapper.state('focused')).toEqual(false);
35
+ });
36
+ });
37
+
38
+ describe('onChange', () => {
39
+ it('sets state.value ', () => {
40
+ const wrapper = mkWrapper();
41
+ wrapper.instance().onChange({ target: { value: 'boo' } });
42
+ expect(wrapper.state('value')).toEqual('boo');
43
+ });
44
+ });
45
+
46
+ describe('onKeyDown', () => {
47
+ it('calls onChange on enter', () => {
48
+ const wrapper = mkWrapper();
49
+ wrapper.setState({ value: 'banana' });
50
+ wrapper.instance().onKeyDown({ keyCode: 13 });
51
+ expect(onChange).toBeCalledWith(['foo', 'banana']);
52
+ });
53
+
54
+ it('doesnt calls onChange on enter if the value is the same as a value in tags', () => {
55
+ const wrapper = mkWrapper();
56
+ wrapper.setState({ value: 'foo' });
57
+ wrapper.instance().onKeyDown({ keyCode: 13 });
58
+ expect(onChange).not.toBeCalled();
59
+ });
60
+ });
61
+ });
62
+ });
package/README.md DELETED
@@ -1,12 +0,0 @@
1
- # install
2
-
3
- ```
4
- npm install
5
- ```
6
-
7
- # demo
8
-
9
- ```
10
- cd demo
11
- ../node_modules/.bin/webpack-dev-server --hot --inline
12
- ```
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/alert-dialog.jsx"],"names":["AlertDialog","text","title","onClose","onConfirm","open","propTypes","PropTypes","string","func","bool"],"mappings":";;;;;;;;;AAAA;;AACA;;AACA;;AAEA,IAAMA,WAAW,GAAG,SAAdA,WAAc;AAAA,MAAGC,IAAH,QAAGA,IAAH;AAAA,MAASC,KAAT,QAASA,KAAT;AAAA,MAAgBC,OAAhB,QAAgBA,OAAhB;AAAA,MAAyBC,SAAzB,QAAyBA,SAAzB;AAAA,MAAoCC,IAApC,QAAoCA,IAApC;AAAA,sBAClB,gCAAC,YAAD;AAAQ,IAAA,IAAI,EAAEA,IAAd;AAAoB,IAAA,OAAO,EAAEF;AAA7B,KACGD,KAAK,iBAAI,gCAAC,iBAAD,QAAcA,KAAd,CADZ,EAEGD,IAAI,iBACH,gCAAC,mBAAD,qBACE,gCAAC,uBAAD,QAAoBA,IAApB,CADF,CAHJ,eAOE,gCAAC,mBAAD,QACGE,OAAO,iBACN,gCAAC,YAAD;AAAQ,IAAA,OAAO,EAAEA,OAAjB;AAA0B,IAAA,KAAK,EAAC;AAAhC,cAFJ,EAMGC,SAAS,iBACR,gCAAC,YAAD;AAAQ,IAAA,SAAS,MAAjB;AAAkB,IAAA,OAAO,EAAEA,SAA3B;AAAsC,IAAA,KAAK,EAAC;AAA5C,UAPJ,CAPF,CADkB;AAAA,CAApB;;AAuBAJ,WAAW,CAACM,SAAZ,GAAwB;AACtBL,EAAAA,IAAI,EAAEM,sBAAUC,MADM;AAEtBN,EAAAA,KAAK,EAAEK,sBAAUC,MAFK;AAGtBL,EAAAA,OAAO,EAAEI,sBAAUE,IAHG;AAItBL,EAAAA,SAAS,EAAEG,sBAAUE,IAJC;AAKtBJ,EAAAA,IAAI,EAAEE,sBAAUG;AALM,CAAxB;eAQeV,W","sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle } from '@material-ui/core';\n\nconst AlertDialog = ({ text, title, onClose, onConfirm, open }) => (\n <Dialog open={open} onClose={onClose}>\n {title && <DialogTitle>{title}</DialogTitle>}\n {text && (\n <DialogContent>\n <DialogContentText>{text}</DialogContentText>\n </DialogContent>\n )}\n <DialogActions>\n {onClose && (\n <Button onClick={onClose} color=\"primary\">\n CANCEL\n </Button>\n )}\n {onConfirm && (\n <Button autoFocus onClick={onConfirm} color=\"primary\">\n OK\n </Button>\n )}\n </DialogActions>\n </Dialog>\n);\n\nAlertDialog.propTypes = {\n text: PropTypes.string,\n title: PropTypes.string,\n onClose: PropTypes.func,\n onConfirm: PropTypes.func,\n open: PropTypes.bool,\n};\n\nexport default AlertDialog;\n"],"file":"alert-dialog.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/checkbox.jsx"],"names":["Checkbox","mini","checked","onChange","value","label","classes","error","miniLabel","miniCheckbox","propTypes","PropTypes","bool","object","isRequired","func","string","defaultProps","theme","fontSize","typography","transform","color","margin","padding","width","spacing","unit","height","marginLeft","grey","palette","main"],"mappings":";;;;;;;;;;;AAAA;;AACA;;AACA;;AACA;;AACA;;AACA;;AACA;;AAEA,IAAMA,QAAQ,GAAG,SAAXA,QAAW;AAAA;;AAAA,MAAGC,IAAH,QAAGA,IAAH;AAAA,MAASC,OAAT,QAASA,OAAT;AAAA,MAAkBC,QAAlB,QAAkBA,QAAlB;AAAA,MAA4BC,KAA5B,QAA4BA,KAA5B;AAAA,MAAmCC,KAAnC,QAAmCA,KAAnC;AAAA,MAA0CC,OAA1C,QAA0CA,OAA1C;AAAA,MAAmDC,KAAnD,QAAmDA,KAAnD;AAAA,sBACf,gCAAC,4BAAD;AACE,IAAA,SAAS,EAAE,4BAAWD,OAAO,CAACL,IAAnB,CADb;AAEE,IAAA,OAAO,EAAE;AACPI,MAAAA,KAAK,EAAE,4BAAWC,OAAO,CAACD,KAAnB,uCAA6BC,OAAO,CAACE,SAArC,EAAiDP,IAAjD;AADA,KAFX;AAKE,IAAA,OAAO,eACL,gCAAC,oBAAD;AACE,MAAA,OAAO,EAAEC,OADX;AAEE,MAAA,QAAQ,EAAEC,QAFZ;AAGE,MAAA,KAAK,EAAEC,KAHT;AAIE,MAAA,SAAS,EAAE,+FAAcE,OAAO,CAACG,YAAtB,EAAqCR,IAArC,kDAA4CK,OAAO,CAACC,KAApD,EAA4DA,KAA5D;AAJb,MANJ;AAaE,IAAA,KAAK,EAAEF;AAbT,IADe;AAAA,CAAjB;;AAkBAL,QAAQ,CAACU,SAAT,GAAqB;AACnBT,EAAAA,IAAI,EAAEU,sBAAUC,IADG;AAEnBN,EAAAA,OAAO,EAAEK,sBAAUE,MAAV,CAAiBC,UAFP;AAGnBZ,EAAAA,OAAO,EAAES,sBAAUC,IAAV,CAAeE,UAHL;AAInBX,EAAAA,QAAQ,EAAEQ,sBAAUI,IAAV,CAAeD,UAJN;AAKnBV,EAAAA,KAAK,EAAEO,sBAAUK,MALE;AAMnBX,EAAAA,KAAK,EAAEM,sBAAUK,MAAV,CAAiBF;AANL,CAArB;AASAd,QAAQ,CAACiB,YAAT,GAAwB;AACtBb,EAAAA,KAAK,EAAE,EADe;AAEtBH,EAAAA,IAAI,EAAE;AAFgB,CAAxB;;eAKe,wBAAW,UAACiB,KAAD;AAAA,SAAY;AACpCb,IAAAA,KAAK,EAAE;AACLc,MAAAA,QAAQ,EAAED,KAAK,CAACE,UAAN,CAAiBD,QAAjB,GAA4B,CADjC;AAELE,MAAAA,SAAS,EAAE,oBAFN;AAGLC,MAAAA,KAAK,EAAE;AAHF,KAD6B;AAMpCb,IAAAA,YAAY,EAAE;AACZc,MAAAA,MAAM,EAAE,CADI;AAEZC,MAAAA,OAAO,EAAE,CAFG;AAGZC,MAAAA,KAAK,EAAEP,KAAK,CAACQ,OAAN,CAAcC,IAAd,GAAqB,CAHhB;AAIZC,MAAAA,MAAM,EAAEV,KAAK,CAACQ,OAAN,CAAcC,IAAd,GAAqB;AAJjB,KANsB;AAYpCnB,IAAAA,SAAS,EAAE;AACTqB,MAAAA,UAAU,EAAEX,KAAK,CAACQ,OAAN,CAAcC,IADjB;AAETL,MAAAA,KAAK,EAAEQ,iBAAK,GAAL,CAFE;AAGTX,MAAAA,QAAQ,EAAED,KAAK,CAACE,UAAN,CAAiBD,QAAjB,GAA4B;AAH7B,KAZyB;AAiBpClB,IAAAA,IAAI,EAAE;AACJsB,MAAAA,MAAM,EAAE,CADJ;AAEJM,MAAAA,UAAU,EAAE,CAFR;AAGJL,MAAAA,OAAO,EAAE;AAHL,KAjB8B;AAsBpCjB,IAAAA,KAAK,EAAE;AACLe,MAAAA,KAAK,EAAEJ,KAAK,CAACa,OAAN,CAAcxB,KAAd,CAAoByB;AADtB;AAtB6B,GAAZ;AAAA,CAAX,EAyBXhC,QAzBW,C","sourcesContent":["import FormControlLabel from '@material-ui/core/FormControlLabel';\nimport MuiCheckbox from '@material-ui/core/Checkbox';\nimport PropTypes from 'prop-types';\nimport React from 'react';\nimport { withStyles } from '@material-ui/core/styles';\nimport classNames from 'classnames';\nimport grey from '@material-ui/core/colors/grey';\n\nconst Checkbox = ({ mini, checked, onChange, value, label, classes, error }) => (\n <FormControlLabel\n className={classNames(classes.mini)}\n classes={{\n label: classNames(classes.label, { [classes.miniLabel]: mini }),\n }}\n control={\n <MuiCheckbox\n checked={checked}\n onChange={onChange}\n value={value}\n className={classNames({ [classes.miniCheckbox]: mini, [classes.error]: error })}\n />\n }\n label={label}\n />\n);\n\nCheckbox.propTypes = {\n mini: PropTypes.bool,\n classes: PropTypes.object.isRequired,\n checked: PropTypes.bool.isRequired,\n onChange: PropTypes.func.isRequired,\n value: PropTypes.string,\n label: PropTypes.string.isRequired,\n};\n\nCheckbox.defaultProps = {\n value: '',\n mini: false,\n};\n\nexport default withStyles((theme) => ({\n label: {\n fontSize: theme.typography.fontSize - 1,\n transform: 'translate(-4%, 2%)',\n color: 'rgba(0,0,0,1.0)',\n },\n miniCheckbox: {\n margin: 0,\n padding: 0,\n width: theme.spacing.unit * 3,\n height: theme.spacing.unit * 3,\n },\n miniLabel: {\n marginLeft: theme.spacing.unit,\n color: grey[700],\n fontSize: theme.typography.fontSize - 3,\n },\n mini: {\n margin: 0,\n marginLeft: 0,\n padding: 0,\n },\n error: {\n color: theme.palette.error.main,\n },\n}))(Checkbox);\n"],"file":"checkbox.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/choice-configuration/feedback-menu.jsx"],"names":["IconMenu","props","event","setState","open","anchorEl","currentTarget","state","undefined","opts","onClick","keys","Object","handleMenuClick","key","handleRequestClose","handleClick","iconButtonElement","map","k","index","React","Component","PropTypes","object","func","isRequired","any","FeedbackMenu","value","onChange","classes","t","type","iconColor","tooltip","icon","none","custom"],"mappings":"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","sourcesContent":["import Menu from '@material-ui/core/Menu';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport ActionFeedback from '@material-ui/icons/Feedback';\nimport IconButton from '@material-ui/core/IconButton';\nimport PropTypes from 'prop-types';\nimport React from 'react';\n\nexport class IconMenu extends React.Component {\n static propTypes = {\n opts: PropTypes.object,\n onClick: PropTypes.func.isRequired,\n iconButtonElement: PropTypes.any,\n };\n\n constructor(props) {\n super(props);\n this.state = {\n anchorEl: undefined,\n open: false,\n };\n }\n\n handleClick = (event) => {\n this.setState({ open: true, anchorEl: event.currentTarget });\n };\n\n handleRequestClose = () => {\n this.setState({ open: false });\n };\n\n render() {\n const { opts, onClick } = this.props;\n const keys = Object.keys(opts);\n\n const handleMenuClick = (key) => () => {\n onClick(key);\n this.handleRequestClose();\n };\n\n return (\n <div>\n <div onClick={this.handleClick}>{this.props.iconButtonElement}</div>\n <Menu id=\"simple-menu\" anchorEl={this.state.anchorEl} open={this.state.open} onClose={this.handleRequestClose}>\n {keys.map((k, index) => (\n <MenuItem key={index} onClick={handleMenuClick(k)}>\n {opts[k]}\n </MenuItem>\n ))}\n </Menu>\n </div>\n );\n }\n}\n\nexport default class FeedbackMenu extends React.Component {\n static propTypes = {\n value: PropTypes.object,\n onChange: PropTypes.func.isRequired,\n classes: PropTypes.object.isRequired,\n };\n\n static defaultProps = {\n classes: {},\n };\n\n render() {\n const { value, onChange, classes } = this.props;\n const t = value && value.type;\n const iconColor = t === 'custom' || t === 'default' ? 'primary' : 'disabled';\n const tooltip = t === 'custom' ? 'Custom Feedback' : t === 'default' ? 'Default Feedback' : 'Feedback disabled';\n\n const icon = (\n <IconButton className={classes.icon} aria-label={tooltip}>\n <ActionFeedback color={iconColor} />\n </IconButton>\n );\n\n return (\n <IconMenu\n iconButtonElement={icon}\n onClick={(key) => onChange(key)}\n opts={{\n none: 'No Feedback',\n default: 'Default',\n custom: 'Custom',\n }}\n />\n );\n }\n}\n"],"file":"feedback-menu.js"}