@pie-lib/config-ui 12.0.0-beta.4 → 12.0.0-next.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 (120) hide show
  1. package/CHANGELOG.json +8 -1653
  2. package/CHANGELOG.md +540 -58
  3. package/LICENSE.md +5 -0
  4. package/NEXT.CHANGELOG.json +1 -0
  5. package/lib/alert-dialog.js +44 -20
  6. package/lib/alert-dialog.js.map +1 -1
  7. package/lib/checkbox.js +59 -61
  8. package/lib/checkbox.js.map +1 -1
  9. package/lib/choice-configuration/feedback-menu.js +30 -65
  10. package/lib/choice-configuration/feedback-menu.js.map +1 -1
  11. package/lib/choice-configuration/index.js +231 -244
  12. package/lib/choice-configuration/index.js.map +1 -1
  13. package/lib/choice-utils.js +7 -19
  14. package/lib/choice-utils.js.map +1 -1
  15. package/lib/feedback-config/feedback-selector.js +89 -115
  16. package/lib/feedback-config/feedback-selector.js.map +1 -1
  17. package/lib/feedback-config/group.js +28 -42
  18. package/lib/feedback-config/group.js.map +1 -1
  19. package/lib/feedback-config/index.js +55 -87
  20. package/lib/feedback-config/index.js.map +1 -1
  21. package/lib/form-section.js +32 -34
  22. package/lib/form-section.js.map +1 -1
  23. package/lib/help.js +41 -80
  24. package/lib/help.js.map +1 -1
  25. package/lib/index.js +2 -32
  26. package/lib/index.js.map +1 -1
  27. package/lib/input.js +24 -57
  28. package/lib/input.js.map +1 -1
  29. package/lib/inputs.js +62 -88
  30. package/lib/inputs.js.map +1 -1
  31. package/lib/langs.js +59 -102
  32. package/lib/langs.js.map +1 -1
  33. package/lib/layout/config-layout.js +95 -67
  34. package/lib/layout/config-layout.js.map +1 -1
  35. package/lib/layout/index.js +1 -4
  36. package/lib/layout/index.js.map +1 -1
  37. package/lib/layout/layout-contents.js +130 -75
  38. package/lib/layout/layout-contents.js.map +1 -1
  39. package/lib/layout/settings-box.js +28 -58
  40. package/lib/layout/settings-box.js.map +1 -1
  41. package/lib/mui-box/index.js +42 -58
  42. package/lib/mui-box/index.js.map +1 -1
  43. package/lib/number-text-field-custom.js +164 -152
  44. package/lib/number-text-field-custom.js.map +1 -1
  45. package/lib/number-text-field.js +87 -119
  46. package/lib/number-text-field.js.map +1 -1
  47. package/lib/radio-with-label.js +33 -26
  48. package/lib/radio-with-label.js.map +1 -1
  49. package/lib/settings/display-size.js +17 -33
  50. package/lib/settings/display-size.js.map +1 -1
  51. package/lib/settings/index.js +26 -46
  52. package/lib/settings/index.js.map +1 -1
  53. package/lib/settings/panel.js +202 -221
  54. package/lib/settings/panel.js.map +1 -1
  55. package/lib/settings/settings-radio-label.js +37 -29
  56. package/lib/settings/settings-radio-label.js.map +1 -1
  57. package/lib/settings/toggle.js +40 -33
  58. package/lib/settings/toggle.js.map +1 -1
  59. package/lib/tabs/index.js +26 -57
  60. package/lib/tabs/index.js.map +1 -1
  61. package/lib/tags-input/index.js +51 -100
  62. package/lib/tags-input/index.js.map +1 -1
  63. package/lib/two-choice.js +47 -91
  64. package/lib/two-choice.js.map +1 -1
  65. package/lib/with-stateful-model.js +11 -34
  66. package/lib/with-stateful-model.js.map +1 -1
  67. package/package.json +22 -11
  68. package/src/__tests__/alert-dialog.test.jsx +283 -0
  69. package/src/__tests__/checkbox.test.jsx +249 -0
  70. package/src/__tests__/choice-utils.test.js +12 -0
  71. package/src/__tests__/form-section.test.jsx +334 -0
  72. package/src/__tests__/help.test.jsx +184 -0
  73. package/src/__tests__/input.test.jsx +192 -0
  74. package/src/__tests__/langs.test.jsx +457 -0
  75. package/src/__tests__/number-text-field-custom.test.jsx +438 -0
  76. package/src/__tests__/number-text-field.test.jsx +341 -0
  77. package/src/__tests__/radio-with-label.test.jsx +259 -0
  78. package/src/__tests__/settings-panel.test.js +187 -0
  79. package/src/__tests__/settings.test.jsx +515 -0
  80. package/src/__tests__/tabs.test.jsx +193 -0
  81. package/src/__tests__/two-choice.test.js +110 -0
  82. package/src/__tests__/with-stateful-model.test.jsx +145 -0
  83. package/src/alert-dialog.jsx +31 -16
  84. package/src/checkbox.jsx +45 -39
  85. package/src/choice-configuration/__tests__/feedback-menu.test.jsx +163 -0
  86. package/src/choice-configuration/__tests__/index.test.jsx +234 -0
  87. package/src/choice-configuration/feedback-menu.jsx +15 -28
  88. package/src/choice-configuration/index.jsx +233 -182
  89. package/src/choice-utils.js +1 -1
  90. package/src/feedback-config/__tests__/feedback-config.test.jsx +141 -0
  91. package/src/feedback-config/__tests__/feedback-selector.test.jsx +107 -0
  92. package/src/feedback-config/feedback-selector.jsx +65 -60
  93. package/src/feedback-config/group.jsx +26 -29
  94. package/src/feedback-config/index.jsx +59 -47
  95. package/src/form-section.jsx +26 -18
  96. package/src/help.jsx +27 -36
  97. package/src/index.js +2 -5
  98. package/src/input.jsx +9 -9
  99. package/src/inputs.jsx +36 -50
  100. package/src/langs.jsx +57 -73
  101. package/src/layout/__tests__/config.layout.test.jsx +59 -0
  102. package/src/layout/__tests__/layout-content.test.jsx +3 -0
  103. package/src/layout/config-layout.jsx +70 -37
  104. package/src/layout/layout-contents.jsx +96 -39
  105. package/src/layout/settings-box.jsx +22 -21
  106. package/src/mui-box/index.jsx +37 -45
  107. package/src/number-text-field-custom.jsx +136 -81
  108. package/src/number-text-field.jsx +59 -37
  109. package/src/radio-with-label.jsx +28 -12
  110. package/src/settings/display-size.jsx +14 -13
  111. package/src/settings/index.js +20 -12
  112. package/src/settings/panel.jsx +147 -110
  113. package/src/settings/settings-radio-label.jsx +29 -13
  114. package/src/settings/toggle.jsx +39 -20
  115. package/src/tabs/index.jsx +15 -19
  116. package/src/tags-input/__tests__/index.test.jsx +113 -0
  117. package/src/tags-input/index.jsx +42 -47
  118. package/src/two-choice.jsx +19 -23
  119. package/src/with-stateful-model.jsx +5 -5
  120. package/README.md +0 -12
@@ -0,0 +1,107 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import React from 'react';
4
+ import { FeedbackSelector } from '../feedback-selector';
5
+
6
+ // Mock the editable-html component to avoid window dependencies in tests
7
+ jest.mock('@pie-lib/editable-html', () => {
8
+ return {
9
+ __esModule: true,
10
+ default: ({ markup, onChange }) => (
11
+ <textarea
12
+ data-testid="editable-html"
13
+ defaultValue={markup || ''}
14
+ onChange={(e) => onChange(e.target.value)}
15
+ />
16
+ ),
17
+ };
18
+ });
19
+
20
+ describe('feedback-selector', () => {
21
+ let onChange;
22
+
23
+ const renderComponent = (feedback = { type: 'default', default: 'hi' }) => {
24
+ return render(
25
+ <FeedbackSelector
26
+ label={'Feedback'}
27
+ onChange={onChange}
28
+ feedback={feedback}
29
+ />
30
+ );
31
+ };
32
+
33
+ beforeEach(() => {
34
+ onChange = jest.fn();
35
+ });
36
+
37
+ describe('rendering', () => {
38
+ it('renders feedback type selector', () => {
39
+ renderComponent();
40
+ expect(screen.getByText('Simple Feedback')).toBeInTheDocument();
41
+ expect(screen.getByText('No Feedback')).toBeInTheDocument();
42
+ expect(screen.getByText('Customized Feedback')).toBeInTheDocument();
43
+ });
44
+
45
+ it('shows default feedback text when type is default', () => {
46
+ renderComponent({ type: 'default', default: 'hi' });
47
+ expect(screen.getByText('hi')).toBeInTheDocument();
48
+ });
49
+
50
+ it('shows editable html when type is custom', () => {
51
+ renderComponent({ type: 'custom', default: 'hi', custom: 'custom text' });
52
+ expect(screen.getByTestId('editable-html')).toBeInTheDocument();
53
+ expect(screen.getByTestId('editable-html')).toHaveValue('custom text');
54
+ });
55
+
56
+ it('does not show default feedback when type is none', () => {
57
+ renderComponent({ type: 'none', default: 'hi' });
58
+ expect(screen.queryByText('hi')).not.toBeInTheDocument();
59
+ });
60
+ });
61
+
62
+ describe('user interactions', () => {
63
+ it('calls onChange when switching to default feedback', async () => {
64
+ const user = userEvent.setup();
65
+ renderComponent({ type: 'custom', default: 'hi' });
66
+
67
+ await user.click(screen.getByLabelText('Simple Feedback'));
68
+
69
+ expect(onChange).toHaveBeenCalledWith({ type: 'default', default: 'hi' });
70
+ });
71
+
72
+ it('calls onChange when switching to custom feedback', async () => {
73
+ const user = userEvent.setup();
74
+ renderComponent({ type: 'default', default: 'hi' });
75
+
76
+ await user.click(screen.getByLabelText('Customized Feedback'));
77
+
78
+ expect(onChange).toHaveBeenCalledWith({ type: 'custom', default: 'hi' });
79
+ });
80
+
81
+ it('calls onChange when switching to no feedback', async () => {
82
+ const user = userEvent.setup();
83
+ renderComponent({ type: 'default', default: 'hi' });
84
+
85
+ await user.click(screen.getByLabelText('No Feedback'));
86
+
87
+ expect(onChange).toHaveBeenCalledWith({ type: 'none', default: 'hi' });
88
+ });
89
+
90
+ it('calls onChange with custom text when editing custom feedback', async () => {
91
+ const user = userEvent.setup();
92
+ renderComponent({ type: 'custom', default: 'hi', custom: '' });
93
+
94
+ const editor = screen.getByTestId('editable-html');
95
+ await user.clear(editor);
96
+ await user.type(editor, 'text');
97
+
98
+ // user.type triggers onChange for each character, so check that onChange was called
99
+ // and that the last call has 'text' in custom field
100
+ expect(onChange).toHaveBeenCalled();
101
+ const lastCall = onChange.mock.calls[onChange.mock.calls.length - 1][0];
102
+ expect(lastCall.type).toBe('custom');
103
+ expect(lastCall.custom).toBe('text');
104
+ expect(lastCall.default).toBe('hi');
105
+ });
106
+ });
107
+ });
@@ -1,116 +1,121 @@
1
- import EditableHTML from '@pie-lib/editable-html';
1
+ //import EditableHTML from '@pie-lib/editable-html';
2
2
  import { InputContainer } from '@pie-lib/render-ui';
3
3
  import PropTypes from 'prop-types';
4
4
  import React from 'react';
5
- import { withStyles } from '@material-ui/core/styles';
5
+ import { styled } from '@mui/material/styles';
6
6
  import Group from './group';
7
7
 
8
+
9
+ // - mathquill error window not defined
10
+ let EditableHtml;
11
+ let StyledEditableHTML;
12
+ if (typeof window !== 'undefined') {
13
+ EditableHtml = require('@pie-lib/editable-html')['default'];
14
+ StyledEditableHTML = styled(EditableHtml)(({ theme }) => ({
15
+ fontFamily: theme.typography.fontFamily,
16
+ }));
17
+ }
18
+
8
19
  const feedbackLabels = {
9
20
  default: 'Simple Feedback',
10
21
  none: 'No Feedback',
11
- custom: 'Customized Feedback'
22
+ custom: 'Customized Feedback',
12
23
  };
13
24
 
14
- const holder = (theme, extras) => ({
25
+ const StyledFeedbackSelector = styled('div')(({ theme }) => ({
26
+ marginBottom: theme.spacing(1),
27
+ }));
28
+
29
+ const StyledInputContainer = styled(InputContainer)(() => ({
30
+ paddingBottom: 0,
31
+ }));
32
+
33
+ const StyledCustomHolder = styled('div')(({ theme }) => ({
15
34
  marginTop: '0px',
16
- background: '#e0dee0',
17
- padding: theme.spacing.unit * 0.9,
18
- marginBottom: theme.spacing.unit * 2,
19
- ...extras
20
- });
21
-
22
- const style = theme => ({
23
- feedbackSelector: {
24
- marginBottom: theme.spacing.unit
25
- },
26
- label: {
27
- cursor: 'pointer'
28
- },
29
- inputContainerLabel: {
30
- transform: 'translateY(-20%)'
31
- },
32
- feedbackInputContainer: {
33
- paddingBottom: 0
34
- },
35
- customHolder: holder(theme, {
36
- background: '#e0dee0',
37
- padding: 0
38
- }),
39
- defaultHolder: holder(theme, {
40
- fontFamily: theme.typography.fontFamily,
41
- cursor: 'default'
42
- }),
43
- editor: {
44
- fontFamily: theme.typography.fontFamily
45
- },
46
- group: {
47
- paddingTop: theme.spacing.unit
48
- }
49
- });
35
+ background: theme.palette.grey[300],
36
+ padding: 0,
37
+ marginBottom: theme.spacing(2),
38
+ borderRadius: '4px',
39
+ }));
40
+
41
+ const StyledDefaultHolder = styled('div')(({ theme }) => ({
42
+ marginTop: '0px',
43
+ background: theme.palette.grey[300],
44
+ padding: theme.spacing(2),
45
+ marginBottom: theme.spacing(2),
46
+ borderRadius: '4px',
47
+ fontFamily: theme.typography.fontFamily,
48
+ cursor: 'default',
49
+ }));
50
+
51
+ const StyledGroup = styled(Group)(({ theme }) => ({
52
+ paddingTop: theme.spacing(1),
53
+ }));
50
54
 
51
55
  export const FeedbackType = {
52
56
  type: PropTypes.oneOf(['default', 'custom', 'none']),
53
57
  default: PropTypes.string,
54
- custom: PropTypes.string
58
+ custom: PropTypes.string,
55
59
  };
56
60
 
57
61
  export class FeedbackSelector extends React.Component {
58
62
  static propTypes = {
59
63
  keys: PropTypes.arrayOf(PropTypes.string),
60
- classes: PropTypes.object.isRequired,
61
64
  label: PropTypes.string.isRequired,
62
65
  feedback: PropTypes.shape(FeedbackType).isRequired,
63
66
  onChange: PropTypes.func.isRequired,
64
- toolbarOpts: PropTypes.object
67
+ toolbarOpts: PropTypes.object,
68
+ mathMlOptions: PropTypes.object,
65
69
  };
66
70
 
67
- changeType = type => {
71
+ changeType = (type) => {
68
72
  const { onChange, feedback } = this.props;
73
+
69
74
  onChange({ ...feedback, type });
70
75
  };
71
76
 
72
- changeCustom = custom => {
77
+ changeCustom = (custom) => {
73
78
  const { onChange, feedback } = this.props;
79
+
74
80
  onChange({ ...feedback, type: 'custom', custom });
75
81
  };
76
82
 
77
83
  render() {
78
- const { keys, classes, label, feedback, toolbarOpts } = this.props;
84
+ const { keys, label, feedback, toolbarOpts, mathMlOptions = {} } = this.props;
79
85
 
80
86
  const feedbackKeys = keys || Object.keys(feedbackLabels);
81
87
 
82
88
  return (
83
- <div className={classes.feedbackSelector}>
84
- <InputContainer
89
+ <StyledFeedbackSelector>
90
+ <StyledInputContainer
85
91
  label={label}
86
- className={classes.feedbackInputContainer}
87
- extraClasses={{ label: classes.inputContainerLabel }}
92
+ extraClasses={{ label: { transform: 'translateY(-20%)' } }}
88
93
  >
89
- <Group
90
- className={classes.group}
94
+ <StyledGroup
91
95
  keys={feedbackKeys}
92
96
  label={label}
93
97
  value={feedback.type}
94
98
  onChange={this.changeType}
95
99
  feedbackLabels={feedbackLabels}
96
100
  />
97
- </InputContainer>
101
+ </StyledInputContainer>
102
+
98
103
  {feedback.type === 'custom' && (
99
- <div className={classes.customHolder}>
100
- <EditableHTML
101
- className={classes.editor}
104
+ <StyledCustomHolder>
105
+ <StyledEditableHTML
102
106
  onChange={this.changeCustom}
103
107
  markup={feedback.custom || ''}
104
108
  toolbarOpts={toolbarOpts}
109
+ languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
110
+ mathMlOptions={mathMlOptions}
105
111
  />
106
- </div>
112
+ </StyledCustomHolder>
107
113
  )}
108
- {feedback.type === 'default' && (
109
- <div className={classes.defaultHolder}> {feedback.default}</div>
110
- )}
111
- </div>
114
+
115
+ {feedback.type === 'default' && <StyledDefaultHolder> {feedback.default}</StyledDefaultHolder>}
116
+ </StyledFeedbackSelector>
112
117
  );
113
118
  }
114
119
  }
115
120
 
116
- export default withStyles(style)(FeedbackSelector);
121
+ export default FeedbackSelector;
@@ -1,44 +1,42 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import RadioWithLabel from '../radio-with-label';
3
3
  import React from 'react';
4
- import { withStyles } from '@material-ui/core/styles';
5
- import classNames from 'classnames';
4
+ import { styled } from '@mui/material/styles';
6
5
 
7
- const styles = () => ({
8
- radioLabel: {
9
- fontSize: '12px'
10
- },
11
- choice: {
12
- display: 'flex',
13
- alignItems: 'center'
6
+ const StyledChoiceHolder = styled('div')(() => ({
7
+ display: 'flex',
8
+ alignItems: 'center',
9
+ }));
10
+
11
+ const StyledChoice = styled('div')(() => ({
12
+ display: 'flex',
13
+ alignItems: 'center',
14
+ }));
15
+
16
+ const StyledRadioWithLabel = styled(RadioWithLabel)(({ theme }) => ({
17
+ '& .MuiFormControlLabel-label': {
18
+ fontSize: theme.typography.fontSize - 2,
14
19
  },
15
- choiceHolder: {
16
- display: 'flex',
17
- alignItems: 'center'
18
- }
19
- });
20
+ }));
20
21
 
21
- const Group = props => {
22
- const { feedbackLabels, value, classes, className, onChange, keys } = props;
22
+ const Group = (props) => {
23
+ const { feedbackLabels, value, className, onChange, keys } = props;
23
24
 
24
25
  return (
25
- <div className={classNames(classes.choiceHolder, className)}>
26
- {keys.map(key => {
26
+ <StyledChoiceHolder className={className}>
27
+ {keys.map((key) => {
27
28
  return (
28
- <div className={classes.choice} key={key}>
29
- <RadioWithLabel
29
+ <StyledChoice key={key}>
30
+ <StyledRadioWithLabel
30
31
  value={key}
31
32
  checked={value === key}
32
- classes={{
33
- label: classes.radioLabel
34
- }}
35
- onChange={e => onChange(e.currentTarget.value)}
33
+ onChange={(e) => onChange(e.currentTarget.value)}
36
34
  label={feedbackLabels[key]}
37
35
  />
38
- </div>
36
+ </StyledChoice>
39
37
  );
40
38
  })}
41
- </div>
39
+ </StyledChoiceHolder>
42
40
  );
43
41
  };
44
42
 
@@ -46,9 +44,8 @@ Group.propTypes = {
46
44
  className: PropTypes.string,
47
45
  feedbackLabels: PropTypes.object.isRequired,
48
46
  value: PropTypes.string.isRequired,
49
- classes: PropTypes.object.isRequired,
50
47
  keys: PropTypes.arrayOf(PropTypes.string),
51
- onChange: PropTypes.func
48
+ onChange: PropTypes.func,
52
49
  };
53
50
 
54
- export default withStyles(styles)(Group);
51
+ export default Group;
@@ -1,98 +1,110 @@
1
1
  import FeedbackSelector, { FeedbackType } from './feedback-selector';
2
2
  import PropTypes from 'prop-types';
3
3
  import React from 'react';
4
- import { withStyles } from '@material-ui/core/styles';
5
- import ExpansionPanel from '@material-ui/core/ExpansionPanel';
6
- import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
7
- import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
8
- import Typography from '@material-ui/core/Typography';
9
- import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
4
+ import { styled } from '@mui/material/styles';
5
+ import Accordion from '@mui/material/Accordion';
6
+ import AccordionSummary from '@mui/material/AccordionSummary';
7
+ import AccordionDetails from '@mui/material/AccordionDetails';
8
+ import Typography from '@mui/material/Typography';
9
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
10
10
  import merge from 'lodash/merge';
11
11
 
12
12
  export { FeedbackSelector };
13
13
 
14
- const style = {
15
- feedbackContainer: {
16
- display: 'flex',
17
- flexDirection: 'column'
18
- }
19
- };
14
+ const StyledFeedbackContainer = styled('div')(() => ({
15
+ display: 'flex',
16
+ flex: 1,
17
+ flexDirection: 'column',
18
+ }));
19
+
20
+ const StyledAccordionDetails = styled(AccordionDetails)(() => ({
21
+ paddingTop: 0,
22
+ paddingBottom: 0,
23
+ }));
20
24
 
21
- export const buildDefaults = input => {
25
+ export const buildDefaults = (input) => {
22
26
  return merge(
23
27
  {},
24
28
  {
25
29
  correct: { type: 'default', default: 'Correct' },
26
30
  incorrect: { type: 'default', default: 'Incorrect' },
27
- partial: { type: 'default', default: 'Nearly' }
31
+ partial: { type: 'default', default: 'Nearly' },
28
32
  },
29
- input
33
+ input,
30
34
  );
31
35
  };
32
36
 
33
37
  export class FeedbackConfig extends React.Component {
34
38
  static propTypes = {
35
39
  allowPartial: PropTypes.bool,
40
+ className: PropTypes.string,
36
41
  feedback: PropTypes.shape({
37
42
  correct: PropTypes.shape(FeedbackType),
38
43
  incorrect: PropTypes.shape(FeedbackType),
39
- partial: PropTypes.shape(FeedbackType)
44
+ partial: PropTypes.shape(FeedbackType),
40
45
  }),
41
46
  onChange: PropTypes.func.isRequired,
42
- classes: PropTypes.object.isRequired,
43
- toolbarOpts: PropTypes.object
47
+ toolbarOpts: PropTypes.object,
44
48
  };
45
49
 
46
50
  static defaultProps = {
47
51
  allowPartial: true,
48
- feedback: buildDefaults()
52
+ feedback: buildDefaults(),
49
53
  };
50
54
 
51
55
  onChange(key, config) {
52
56
  const { feedback, onChange } = this.props;
53
57
  const update = { ...feedback, [key]: config };
58
+
54
59
  onChange(update);
55
60
  }
56
61
 
57
62
  onCorrectChange = this.onChange.bind(this, 'correct');
63
+
58
64
  onIncorrectChange = this.onChange.bind(this, 'incorrect');
65
+
59
66
  onPartialChange = this.onChange.bind(this, 'partial');
60
67
 
61
68
  render() {
62
- const { classes, allowPartial, feedback, toolbarOpts } = this.props;
69
+ const { className, allowPartial, feedback, toolbarOpts } = this.props;
63
70
 
64
71
  return (
65
- <ExpansionPanel>
66
- <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
67
- <Typography className={classes.heading}>Feedback</Typography>
68
- </ExpansionPanelSummary>
69
- <ExpansionPanelDetails>
70
- <div className={classes.feedbackContainer}>
71
- <FeedbackSelector
72
- label="If correct, show"
73
- feedback={feedback.correct}
74
- onChange={this.onCorrectChange}
75
- toolbarOpts={toolbarOpts}
76
- />
77
- {allowPartial && (
72
+ <div className={className}>
73
+ <Accordion slotProps={{ transition: { timeout: { enter: 225, exit: 195 } } }}>
74
+ <AccordionSummary expandIcon={<ExpandMoreIcon />}>
75
+ <Typography>Feedback</Typography>
76
+ </AccordionSummary>
77
+
78
+ <StyledAccordionDetails>
79
+ <StyledFeedbackContainer>
80
+ <FeedbackSelector
81
+ label="If correct, show"
82
+ feedback={feedback.correct}
83
+ onChange={this.onCorrectChange}
84
+ toolbarOpts={toolbarOpts}
85
+ />
86
+
87
+ {allowPartial && (
88
+ <FeedbackSelector
89
+ label="If partially correct, show"
90
+ feedback={feedback.partial}
91
+ onChange={this.onPartialChange}
92
+ toolbarOpts={toolbarOpts}
93
+ />
94
+ )}
95
+
78
96
  <FeedbackSelector
79
- label="If partially correct, show"
80
- feedback={feedback.partial}
81
- onChange={this.onPartialChange}
97
+ label="If incorrect, show"
98
+ feedback={feedback.incorrect}
99
+ onChange={this.onIncorrectChange}
82
100
  toolbarOpts={toolbarOpts}
83
101
  />
84
- )}
85
- <FeedbackSelector
86
- label="If incorrect, show"
87
- feedback={feedback.incorrect}
88
- onChange={this.onIncorrectChange}
89
- toolbarOpts={toolbarOpts}
90
- />
91
- </div>
92
- </ExpansionPanelDetails>
93
- </ExpansionPanel>
102
+ </StyledFeedbackContainer>
103
+ </StyledAccordionDetails>
104
+ </Accordion>
105
+ </div>
94
106
  );
95
107
  }
96
108
  }
97
109
 
98
- export default withStyles(style)(FeedbackConfig);
110
+ export default FeedbackConfig;
@@ -1,23 +1,31 @@
1
1
  import React from 'react';
2
- import Typography from '@material-ui/core/Typography';
3
- import classNames from 'classnames';
4
- import { withStyles } from '@material-ui/core/styles';
2
+ import PropTypes from 'prop-types';
3
+ import Typography from '@mui/material/Typography';
4
+ import { styled } from '@mui/material/styles';
5
5
 
6
- const styles = theme => ({
7
- formSection: {
8
- marginTop: theme.spacing.unit * 2,
9
- marginBottom: theme.spacing.unit * 2
10
- },
11
- label: {
12
- marginBottom: theme.spacing.unit
13
- }
14
- });
6
+ const StyledFormSection = styled('div')(({ theme }) => ({
7
+ marginTop: theme.spacing(2),
8
+ marginBottom: theme.spacing(2),
9
+ }));
15
10
 
16
- export default withStyles(styles)(({ className, classes, label, children, labelExtraStyle }) => (
17
- <div className={classNames(classes.formSection, className)}>
18
- <Typography className={classes.label} type="subheading" style={labelExtraStyle}>
11
+ const StyledTypography = styled(Typography)(({ theme }) => ({
12
+ marginBottom: theme.spacing(1),
13
+ }));
14
+
15
+ const FormSection = ({ className, label, children, labelExtraStyle }) => (
16
+ <StyledFormSection className={className}>
17
+ <StyledTypography variant="subtitle1" style={labelExtraStyle}>
19
18
  {label}
20
- </Typography>
19
+ </StyledTypography>
21
20
  {children}
22
- </div>
23
- ));
21
+ </StyledFormSection>
22
+ );
23
+
24
+ FormSection.propTypes = {
25
+ className: PropTypes.string,
26
+ label: PropTypes.string,
27
+ children: PropTypes.node,
28
+ labelExtraStyle: PropTypes.object,
29
+ };
30
+
31
+ export default FormSection;