@pie-lib/config-ui 13.1.0-beta.7 → 14.0.0-next.35

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 (233) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +11 -0
  2. package/dist/alert-dialog.d.ts +44 -0
  3. package/dist/alert-dialog.js +47 -0
  4. package/dist/checkbox.d.ts +34 -0
  5. package/dist/checkbox.js +57 -0
  6. package/dist/choice-configuration/feedback-menu.d.ts +32 -0
  7. package/dist/choice-configuration/feedback-menu.js +85 -0
  8. package/dist/choice-configuration/index.d.ts +62 -0
  9. package/dist/choice-configuration/index.js +240 -0
  10. package/dist/choice-utils.d.ts +21 -0
  11. package/dist/choice-utils.js +15 -0
  12. package/dist/feedback-config/feedback-selector.d.ts +33 -0
  13. package/dist/feedback-config/feedback-selector.js +92 -0
  14. package/dist/feedback-config/group.d.ts +21 -0
  15. package/dist/feedback-config/group.js +33 -0
  16. package/dist/feedback-config/index.d.ts +48 -0
  17. package/dist/feedback-config/index.js +96 -0
  18. package/dist/form-section.d.ts +25 -0
  19. package/dist/form-section.js +25 -0
  20. package/dist/fraction-to-number.d.ts +7 -0
  21. package/dist/fraction-to-number.js +9 -0
  22. package/dist/help.d.ts +41 -0
  23. package/dist/help.js +62 -0
  24. package/dist/index.d.ts +31 -0
  25. package/dist/index.js +34 -0
  26. package/dist/input.d.ts +29 -0
  27. package/dist/input.js +65 -0
  28. package/dist/inputs.d.ts +63 -0
  29. package/dist/inputs.js +70 -0
  30. package/dist/langs.d.ts +41 -0
  31. package/dist/langs.js +76 -0
  32. package/dist/layout/config-layout.d.ts +10 -0
  33. package/dist/layout/config-layout.js +75 -0
  34. package/dist/layout/index.d.ts +11 -0
  35. package/dist/layout/index.js +10 -0
  36. package/dist/layout/layout-contents.d.ts +21 -0
  37. package/dist/layout/layout-contents.js +70 -0
  38. package/dist/layout/settings-box.d.ts +19 -0
  39. package/dist/layout/settings-box.js +32 -0
  40. package/dist/mui-box/index.d.ts +21 -0
  41. package/dist/mui-box/index.js +47 -0
  42. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/extends.js +12 -0
  43. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/inheritsLoose.js +7 -0
  44. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +12 -0
  45. package/dist/node_modules/.bun/@babel_runtime@7.29.7/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +8 -0
  46. package/dist/node_modules/.bun/react-measure@2.5.2_6dbf9a050bc9aadb/node_modules/react-measure/dist/index.esm.js +122 -0
  47. package/dist/node_modules/.bun/resize-observer-polyfill@1.5.1/node_modules/resize-observer-polyfill/dist/ResizeObserver.es.js +276 -0
  48. package/dist/number-text-field-custom.d.ts +51 -0
  49. package/dist/number-text-field-custom.js +192 -0
  50. package/dist/number-text-field.d.ts +47 -0
  51. package/dist/number-text-field.js +122 -0
  52. package/dist/radio-with-label.d.ts +25 -0
  53. package/dist/radio-with-label.js +27 -0
  54. package/dist/settings/display-size.d.ts +26 -0
  55. package/dist/settings/display-size.js +45 -0
  56. package/dist/settings/index.d.ts +45 -0
  57. package/dist/settings/index.js +63 -0
  58. package/dist/settings/panel.d.ts +27 -0
  59. package/dist/settings/panel.js +201 -0
  60. package/dist/settings/settings-radio-label.d.ts +25 -0
  61. package/dist/settings/settings-radio-label.js +29 -0
  62. package/dist/settings/toggle.d.ts +25 -0
  63. package/dist/settings/toggle.js +33 -0
  64. package/dist/tabs/index.d.ts +22 -0
  65. package/dist/tabs/index.js +39 -0
  66. package/dist/tags-input/index.d.ts +21 -0
  67. package/dist/tags-input/index.js +83 -0
  68. package/dist/two-choice.d.ts +43 -0
  69. package/dist/two-choice.js +79 -0
  70. package/dist/with-stateful-model.d.ts +42 -0
  71. package/dist/with-stateful-model.js +32 -0
  72. package/package.json +31 -19
  73. package/CHANGELOG.json +0 -32
  74. package/CHANGELOG.md +0 -2419
  75. package/lib/__tests__/alert-dialog.test.js +0 -262
  76. package/lib/__tests__/alert-dialog.test.js.map +0 -1
  77. package/lib/__tests__/checkbox.test.js +0 -227
  78. package/lib/__tests__/checkbox.test.js.map +0 -1
  79. package/lib/__tests__/choice-utils.test.js +0 -14
  80. package/lib/__tests__/choice-utils.test.js.map +0 -1
  81. package/lib/__tests__/form-section.test.js +0 -252
  82. package/lib/__tests__/form-section.test.js.map +0 -1
  83. package/lib/__tests__/help.test.js +0 -270
  84. package/lib/__tests__/help.test.js.map +0 -1
  85. package/lib/__tests__/input.test.js +0 -268
  86. package/lib/__tests__/input.test.js.map +0 -1
  87. package/lib/__tests__/langs.test.js +0 -541
  88. package/lib/__tests__/langs.test.js.map +0 -1
  89. package/lib/__tests__/number-text-field-custom.test.js +0 -362
  90. package/lib/__tests__/number-text-field-custom.test.js.map +0 -1
  91. package/lib/__tests__/number-text-field.test.js +0 -421
  92. package/lib/__tests__/number-text-field.test.js.map +0 -1
  93. package/lib/__tests__/radio-with-label.test.js +0 -233
  94. package/lib/__tests__/radio-with-label.test.js.map +0 -1
  95. package/lib/__tests__/settings-panel.test.js +0 -184
  96. package/lib/__tests__/settings-panel.test.js.map +0 -1
  97. package/lib/__tests__/settings.test.js +0 -653
  98. package/lib/__tests__/settings.test.js.map +0 -1
  99. package/lib/__tests__/tabs.test.js +0 -211
  100. package/lib/__tests__/tabs.test.js.map +0 -1
  101. package/lib/__tests__/two-choice.test.js +0 -124
  102. package/lib/__tests__/two-choice.test.js.map +0 -1
  103. package/lib/__tests__/with-stateful-model.test.js +0 -221
  104. package/lib/__tests__/with-stateful-model.test.js.map +0 -1
  105. package/lib/alert-dialog.js +0 -68
  106. package/lib/alert-dialog.js.map +0 -1
  107. package/lib/checkbox.js +0 -84
  108. package/lib/checkbox.js.map +0 -1
  109. package/lib/choice-configuration/__tests__/feedback-menu.test.js +0 -287
  110. package/lib/choice-configuration/__tests__/feedback-menu.test.js.map +0 -1
  111. package/lib/choice-configuration/__tests__/index.test.js +0 -253
  112. package/lib/choice-configuration/__tests__/index.test.js.map +0 -1
  113. package/lib/choice-configuration/feedback-menu.js +0 -129
  114. package/lib/choice-configuration/feedback-menu.js.map +0 -1
  115. package/lib/choice-configuration/index.js +0 -381
  116. package/lib/choice-configuration/index.js.map +0 -1
  117. package/lib/choice-utils.js +0 -42
  118. package/lib/choice-utils.js.map +0 -1
  119. package/lib/feedback-config/__tests__/feedback-config.test.js +0 -201
  120. package/lib/feedback-config/__tests__/feedback-config.test.js.map +0 -1
  121. package/lib/feedback-config/__tests__/feedback-selector.test.js +0 -177
  122. package/lib/feedback-config/__tests__/feedback-selector.test.js.map +0 -1
  123. package/lib/feedback-config/feedback-selector.js +0 -155
  124. package/lib/feedback-config/feedback-selector.js.map +0 -1
  125. package/lib/feedback-config/group.js +0 -61
  126. package/lib/feedback-config/group.js.map +0 -1
  127. package/lib/feedback-config/index.js +0 -146
  128. package/lib/feedback-config/index.js.map +0 -1
  129. package/lib/form-section.js +0 -44
  130. package/lib/form-section.js.map +0 -1
  131. package/lib/help.js +0 -106
  132. package/lib/help.js.map +0 -1
  133. package/lib/index.js +0 -186
  134. package/lib/index.js.map +0 -1
  135. package/lib/input.js +0 -106
  136. package/lib/input.js.map +0 -1
  137. package/lib/inputs.js +0 -105
  138. package/lib/inputs.js.map +0 -1
  139. package/lib/langs.js +0 -136
  140. package/lib/langs.js.map +0 -1
  141. package/lib/layout/__tests__/config.layout.test.js +0 -70
  142. package/lib/layout/__tests__/config.layout.test.js.map +0 -1
  143. package/lib/layout/__tests__/layout-content.test.js +0 -6
  144. package/lib/layout/__tests__/layout-content.test.js.map +0 -1
  145. package/lib/layout/config-layout.js +0 -137
  146. package/lib/layout/config-layout.js.map +0 -1
  147. package/lib/layout/index.js +0 -21
  148. package/lib/layout/index.js.map +0 -1
  149. package/lib/layout/layout-contents.js +0 -160
  150. package/lib/layout/layout-contents.js.map +0 -1
  151. package/lib/layout/settings-box.js +0 -57
  152. package/lib/layout/settings-box.js.map +0 -1
  153. package/lib/mui-box/index.js +0 -63
  154. package/lib/mui-box/index.js.map +0 -1
  155. package/lib/number-text-field-custom.js +0 -376
  156. package/lib/number-text-field-custom.js.map +0 -1
  157. package/lib/number-text-field.js +0 -229
  158. package/lib/number-text-field.js.map +0 -1
  159. package/lib/radio-with-label.js +0 -48
  160. package/lib/radio-with-label.js.map +0 -1
  161. package/lib/settings/display-size.js +0 -61
  162. package/lib/settings/display-size.js.map +0 -1
  163. package/lib/settings/index.js +0 -110
  164. package/lib/settings/index.js.map +0 -1
  165. package/lib/settings/panel.js +0 -392
  166. package/lib/settings/panel.js.map +0 -1
  167. package/lib/settings/settings-radio-label.js +0 -51
  168. package/lib/settings/settings-radio-label.js.map +0 -1
  169. package/lib/settings/toggle.js +0 -63
  170. package/lib/settings/toggle.js.map +0 -1
  171. package/lib/tabs/index.js +0 -75
  172. package/lib/tabs/index.js.map +0 -1
  173. package/lib/tags-input/__tests__/index.test.js +0 -183
  174. package/lib/tags-input/__tests__/index.test.js.map +0 -1
  175. package/lib/tags-input/index.js +0 -149
  176. package/lib/tags-input/index.js.map +0 -1
  177. package/lib/two-choice.js +0 -136
  178. package/lib/two-choice.js.map +0 -1
  179. package/lib/with-stateful-model.js +0 -61
  180. package/lib/with-stateful-model.js.map +0 -1
  181. package/src/__tests__/alert-dialog.test.jsx +0 -183
  182. package/src/__tests__/checkbox.test.jsx +0 -152
  183. package/src/__tests__/choice-utils.test.js +0 -12
  184. package/src/__tests__/form-section.test.jsx +0 -328
  185. package/src/__tests__/help.test.jsx +0 -184
  186. package/src/__tests__/input.test.jsx +0 -156
  187. package/src/__tests__/langs.test.jsx +0 -376
  188. package/src/__tests__/number-text-field-custom.test.jsx +0 -255
  189. package/src/__tests__/number-text-field.test.jsx +0 -263
  190. package/src/__tests__/radio-with-label.test.jsx +0 -155
  191. package/src/__tests__/settings-panel.test.js +0 -187
  192. package/src/__tests__/settings.test.jsx +0 -452
  193. package/src/__tests__/tabs.test.jsx +0 -188
  194. package/src/__tests__/two-choice.test.js +0 -110
  195. package/src/__tests__/with-stateful-model.test.jsx +0 -139
  196. package/src/alert-dialog.jsx +0 -75
  197. package/src/checkbox.jsx +0 -61
  198. package/src/choice-configuration/__tests__/feedback-menu.test.jsx +0 -151
  199. package/src/choice-configuration/__tests__/index.test.jsx +0 -234
  200. package/src/choice-configuration/feedback-menu.jsx +0 -96
  201. package/src/choice-configuration/index.jsx +0 -357
  202. package/src/choice-utils.js +0 -30
  203. package/src/feedback-config/__tests__/feedback-config.test.jsx +0 -141
  204. package/src/feedback-config/__tests__/feedback-selector.test.jsx +0 -97
  205. package/src/feedback-config/feedback-selector.jsx +0 -112
  206. package/src/feedback-config/group.jsx +0 -51
  207. package/src/feedback-config/index.jsx +0 -111
  208. package/src/form-section.jsx +0 -31
  209. package/src/help.jsx +0 -79
  210. package/src/index.js +0 -55
  211. package/src/input.jsx +0 -72
  212. package/src/inputs.jsx +0 -69
  213. package/src/langs.jsx +0 -111
  214. package/src/layout/__tests__/config.layout.test.jsx +0 -59
  215. package/src/layout/__tests__/layout-content.test.jsx +0 -3
  216. package/src/layout/config-layout.jsx +0 -103
  217. package/src/layout/index.js +0 -4
  218. package/src/layout/layout-contents.jsx +0 -117
  219. package/src/layout/settings-box.jsx +0 -32
  220. package/src/mui-box/index.jsx +0 -56
  221. package/src/number-text-field-custom.jsx +0 -333
  222. package/src/number-text-field.jsx +0 -215
  223. package/src/radio-with-label.jsx +0 -30
  224. package/src/settings/display-size.jsx +0 -53
  225. package/src/settings/index.js +0 -83
  226. package/src/settings/panel.jsx +0 -333
  227. package/src/settings/settings-radio-label.jsx +0 -32
  228. package/src/settings/toggle.jsx +0 -46
  229. package/src/tabs/index.jsx +0 -47
  230. package/src/tags-input/__tests__/index.test.jsx +0 -113
  231. package/src/tags-input/index.jsx +0 -116
  232. package/src/two-choice.jsx +0 -90
  233. package/src/with-stateful-model.jsx +0 -36
@@ -1,234 +0,0 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import userEvent from '@testing-library/user-event';
4
- import { ChoiceConfiguration } from '../index';
5
-
6
- jest.mock('@pie-lib/editable-html-tip-tap', () => ({
7
- __esModule: true,
8
- default: ({ markup, onChange, disabled }) => (
9
- <textarea
10
- data-testid="editable-html"
11
- defaultValue={markup || ''}
12
- onChange={(e) => onChange(e.target.value)}
13
- disabled={disabled}
14
- />
15
- ),
16
- }));
17
-
18
- const defaultFeedback = {
19
- correct: 'Correct',
20
- incorrect: 'Incorrect',
21
- };
22
-
23
- const data = {
24
- correct: true,
25
- value: 'foo',
26
- label: 'Foo',
27
- feedback: {
28
- type: 'custom',
29
- },
30
- };
31
-
32
- const classes = {
33
- choiceConfiguration: 'choiceConfiguration',
34
- };
35
-
36
- describe('ChoiceConfiguration', () => {
37
- const onChange = jest.fn();
38
-
39
- beforeEach(() => {
40
- onChange.mockClear();
41
- });
42
-
43
- describe('rendering', () => {
44
- it('renders correctly with default props', () => {
45
- const { container } = render(
46
- <ChoiceConfiguration classes={classes} defaultFeedback={defaultFeedback} data={data} onChange={onChange} />,
47
- );
48
- expect(container.firstChild).toBeInTheDocument();
49
- });
50
-
51
- it('renders with checked state', () => {
52
- render(
53
- <ChoiceConfiguration
54
- classes={classes}
55
- defaultFeedback={defaultFeedback}
56
- data={data}
57
- onChange={onChange}
58
- mode="checkbox"
59
- />,
60
- );
61
- const checkbox = screen.getByRole('checkbox');
62
- expect(checkbox).toBeChecked();
63
- });
64
-
65
- it('renders without feedback when allowFeedBack is false', () => {
66
- render(
67
- <ChoiceConfiguration
68
- allowFeedBack={false}
69
- classes={classes}
70
- defaultFeedback={defaultFeedback}
71
- data={data}
72
- onChange={onChange}
73
- />,
74
- );
75
- expect(screen.queryByRole('button', { name: /feedback/i })).not.toBeInTheDocument();
76
- });
77
-
78
- it('renders without delete button when allowDelete is false', () => {
79
- render(
80
- <ChoiceConfiguration
81
- allowDelete={false}
82
- classes={classes}
83
- defaultFeedback={defaultFeedback}
84
- data={data}
85
- onChange={onChange}
86
- />,
87
- );
88
- expect(screen.queryByRole('button', { name: /delete/i })).not.toBeInTheDocument();
89
- });
90
- });
91
-
92
- describe('user interactions', () => {
93
- it('calls onChange when label is edited', async () => {
94
- const user = userEvent.setup();
95
- render(
96
- <ChoiceConfiguration classes={classes} defaultFeedback={defaultFeedback} data={data} onChange={onChange} />,
97
- );
98
-
99
- const editableHtmlElements = screen.getAllByTestId('editable-html');
100
- const editableHtml = editableHtmlElements[0];
101
- await user.clear(editableHtml);
102
- await user.type(editableHtml, 'new label');
103
-
104
- expect(onChange).toHaveBeenCalled();
105
- expect(onChange).toHaveBeenCalledWith(
106
- expect.objectContaining({
107
- label: expect.stringContaining('new label'),
108
- }),
109
- );
110
- });
111
-
112
- it('calls onChange when checkbox is toggled', async () => {
113
- const user = userEvent.setup();
114
- render(
115
- <ChoiceConfiguration
116
- classes={classes}
117
- defaultFeedback={defaultFeedback}
118
- data={{ ...data, correct: false }}
119
- onChange={onChange}
120
- mode="checkbox"
121
- />,
122
- );
123
-
124
- const checkbox = screen.getByRole('checkbox');
125
- await user.click(checkbox);
126
-
127
- expect(onChange).toHaveBeenCalledWith(
128
- expect.objectContaining({
129
- correct: true,
130
- }),
131
- );
132
- });
133
- });
134
-
135
- describe('prop variations', () => {
136
- it('renders with radio mode instead of checkbox', () => {
137
- render(
138
- <ChoiceConfiguration
139
- classes={classes}
140
- defaultFeedback={defaultFeedback}
141
- data={data}
142
- onChange={onChange}
143
- mode="radio"
144
- />,
145
- );
146
- const radio = screen.getByRole('radio');
147
- expect(radio).toBeInTheDocument();
148
- });
149
-
150
- it('renders with disabled state', () => {
151
- render(
152
- <ChoiceConfiguration
153
- classes={classes}
154
- defaultFeedback={defaultFeedback}
155
- data={data}
156
- onChange={onChange}
157
- disabled={true}
158
- mode="checkbox"
159
- />,
160
- );
161
- const checkbox = screen.getByRole('checkbox');
162
- expect(checkbox).toBeInTheDocument();
163
- });
164
-
165
- it('renders with custom feedback type', () => {
166
- render(
167
- <ChoiceConfiguration
168
- classes={classes}
169
- defaultFeedback={defaultFeedback}
170
- data={{ ...data, feedback: { type: 'custom' } }}
171
- onChange={onChange}
172
- mode="checkbox"
173
- />,
174
- );
175
- const editableElements = screen.getAllByTestId('editable-html');
176
- expect(editableElements.length).toBeGreaterThan(0);
177
- });
178
-
179
- it('renders with incorrect answer', () => {
180
- render(
181
- <ChoiceConfiguration
182
- classes={classes}
183
- defaultFeedback={defaultFeedback}
184
- data={{ ...data, correct: false }}
185
- onChange={onChange}
186
- mode="checkbox"
187
- />,
188
- );
189
- const checkbox = screen.getByRole('checkbox');
190
- expect(checkbox).not.toBeChecked();
191
- });
192
- });
193
-
194
- describe('edge cases', () => {
195
- it('handles data with empty label', () => {
196
- render(
197
- <ChoiceConfiguration
198
- classes={classes}
199
- defaultFeedback={defaultFeedback}
200
- data={{ ...data, label: '' }}
201
- onChange={onChange}
202
- />,
203
- );
204
- const editableElements = screen.getAllByTestId('editable-html');
205
- expect(editableElements.length).toBeGreaterThan(0);
206
- });
207
-
208
- it('handles multiple feedback types', () => {
209
- const { rerender } = render(
210
- <ChoiceConfiguration
211
- classes={classes}
212
- defaultFeedback={defaultFeedback}
213
- data={{ ...data, feedback: { type: 'default' } }}
214
- onChange={onChange}
215
- />,
216
- );
217
-
218
- let editableElements = screen.getAllByTestId('editable-html');
219
- expect(editableElements.length).toBeGreaterThan(0);
220
-
221
- rerender(
222
- <ChoiceConfiguration
223
- classes={classes}
224
- defaultFeedback={defaultFeedback}
225
- data={{ ...data, feedback: { type: 'custom' } }}
226
- onChange={onChange}
227
- />,
228
- );
229
-
230
- editableElements = screen.getAllByTestId('editable-html');
231
- expect(editableElements.length).toBeGreaterThan(0);
232
- });
233
- });
234
- });
@@ -1,96 +0,0 @@
1
- import Menu from '@mui/material/Menu';
2
- import MenuItem from '@mui/material/MenuItem';
3
- import ActionFeedback from '@mui/icons-material/Feedback';
4
- import IconButton from '@mui/material/IconButton';
5
- import PropTypes from 'prop-types';
6
- import React from 'react';
7
-
8
- export class IconMenu extends React.Component {
9
- static propTypes = {
10
- opts: PropTypes.object,
11
- onClick: PropTypes.func.isRequired,
12
- iconButtonElement: PropTypes.any,
13
- };
14
-
15
- constructor(props) {
16
- super(props);
17
- this.state = {
18
- anchorEl: undefined,
19
- open: false,
20
- };
21
- }
22
-
23
- handleClick = (event) => {
24
- this.setState({ open: true, anchorEl: event.currentTarget });
25
- };
26
-
27
- handleRequestClose = () => {
28
- this.setState({ open: false });
29
- };
30
-
31
- render() {
32
- const { opts, onClick } = this.props;
33
- const keys = Object.keys(opts);
34
-
35
- const handleMenuClick = (key) => () => {
36
- onClick(key);
37
- this.handleRequestClose();
38
- };
39
-
40
- return (
41
- <div>
42
- <div onClick={this.handleClick}>{this.props.iconButtonElement}</div>
43
- <Menu
44
- id="simple-menu"
45
- anchorEl={this.state.anchorEl}
46
- open={this.state.open}
47
- onClose={this.handleRequestClose}
48
- transitionDuration={{ enter: 225, exit: 195 }}
49
- >
50
- {keys.map((k, index) => (
51
- <MenuItem key={index} onClick={handleMenuClick(k)}>
52
- {opts[k]}
53
- </MenuItem>
54
- ))}
55
- </Menu>
56
- </div>
57
- );
58
- }
59
- }
60
-
61
- export default class FeedbackMenu extends React.Component {
62
- static propTypes = {
63
- value: PropTypes.object,
64
- onChange: PropTypes.func.isRequired,
65
- classes: PropTypes.object.isRequired,
66
- };
67
-
68
- static defaultProps = {
69
- classes: {},
70
- };
71
-
72
- render() {
73
- const { value, onChange, classes } = this.props;
74
- const t = value && value.type;
75
- const iconColor = t === 'custom' || t === 'default' ? 'primary' : 'disabled';
76
- const tooltip = t === 'custom' ? 'Custom Feedback' : t === 'default' ? 'Default Feedback' : 'Feedback disabled';
77
-
78
- const icon = (
79
- <IconButton className={classes.icon} aria-label={tooltip} size="large">
80
- <ActionFeedback color={iconColor} />
81
- </IconButton>
82
- );
83
-
84
- return (
85
- <IconMenu
86
- iconButtonElement={icon}
87
- onClick={(key) => onChange(key)}
88
- opts={{
89
- none: 'No Feedback',
90
- default: 'Default',
91
- custom: 'Custom',
92
- }}
93
- />
94
- );
95
- }
96
- }
@@ -1,357 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { styled } from '@mui/material/styles';
4
- import TextField from '@mui/material/TextField';
5
- import ActionDelete from '@mui/icons-material/Delete';
6
- import ArrowRight from '@mui/icons-material/SubdirectoryArrowRight';
7
- import IconButton from '@mui/material/IconButton';
8
- import { InputContainer } from '@pie-lib/render-ui';
9
- import EditableHtml from '@pie-lib/editable-html-tip-tap';
10
- import { InputCheckbox, InputRadio } from '../inputs';
11
- import FeedbackMenu from './feedback-menu';
12
-
13
- const StyledEditorHolder = styled('div')(({ theme }) => ({
14
- marginTop: theme.spacing(2),
15
- }));
16
-
17
- const EditableHtmlContainer = ({
18
- label,
19
- onChange,
20
- value,
21
- className,
22
- imageSupport,
23
- disableImageAlignmentButtons,
24
- disabled,
25
- spellCheck,
26
- nonEmpty,
27
- pluginOpts,
28
- toolbarOpts,
29
- error,
30
- maxImageWidth,
31
- maxImageHeight,
32
- uploadSoundSupport,
33
- mathMlOptions = {},
34
- }) => {
35
- return (
36
- <InputContainer label={label} className={className}>
37
- <StyledEditorHolder>
38
- <EditableHtml
39
- markup={value || ''}
40
- disabled={disabled}
41
- spellCheck={spellCheck}
42
- nonEmpty={nonEmpty}
43
- onChange={onChange}
44
- imageSupport={imageSupport}
45
- disableImageAlignmentButtons={disableImageAlignmentButtons}
46
- pluginProps={pluginOpts || {}}
47
- toolbarOpts={toolbarOpts}
48
- error={error}
49
- maxImageWidth={maxImageWidth}
50
- maxImageHeight={maxImageHeight}
51
- uploadSoundSupport={uploadSoundSupport}
52
- languageCharactersProps={[{ language: 'spanish' }, { language: 'special' }]}
53
- mathMlOptions={mathMlOptions}
54
- />
55
- </StyledEditorHolder>
56
- </InputContainer>
57
- );
58
- };
59
-
60
- const StyledFeedbackContainer = styled('div')(() => ({
61
- position: 'relative',
62
- }));
63
-
64
- const StyledArrowIcon = styled(ArrowRight)(({ theme }) => ({
65
- fill: theme.palette.grey[400],
66
- left: -56,
67
- position: 'absolute',
68
- top: 40,
69
- }));
70
-
71
- const StyledTextField = styled(TextField)(({ theme }) => ({
72
- width: '100%',
73
- marginTop: theme.spacing(2),
74
- }));
75
-
76
- const StyledEditableHtmlContainer = styled(EditableHtmlContainer)(({ theme }) => ({
77
- width: '100%',
78
- marginTop: theme.spacing(2),
79
- }));
80
-
81
- const Feedback = ({ value, onChange, type, correct, defaults, toolbarOpts, mathMlOptions = {} }) => {
82
- if (!type || type === 'none') {
83
- return null;
84
- } else if (type === 'default') {
85
- return (
86
- <StyledFeedbackContainer>
87
- <StyledArrowIcon />
88
- <StyledTextField
89
- label="Feedback Text"
90
- value={correct ? defaults.correct : defaults.incorrect}
91
- variant="standard"
92
- />
93
- </StyledFeedbackContainer>
94
- );
95
- } else {
96
- return (
97
- <StyledFeedbackContainer>
98
- <StyledArrowIcon />
99
- <StyledEditableHtmlContainer
100
- label="Feedback Text"
101
- value={value}
102
- onChange={onChange}
103
- toolbarOpts={toolbarOpts}
104
- mathMlOptions={mathMlOptions}
105
- />
106
- </StyledFeedbackContainer>
107
- );
108
- }
109
- };
110
-
111
- const StyledIndex = styled('span')(({ theme }) => ({
112
- paddingRight: theme.spacing(1),
113
- paddingTop: theme.spacing(3),
114
- }));
115
-
116
- const StyledTopRow = styled('div')(() => ({
117
- display: 'flex',
118
- alignItems: 'center',
119
- }));
120
-
121
- const StyledToggle = styled('div')(({ theme }) => ({
122
- flex: '0 1 auto',
123
- paddingTop: theme.spacing(0.5),
124
- paddingBottom: 0,
125
- marginRight: 0,
126
- marginLeft: theme.spacing(1),
127
- }));
128
-
129
- const StyledFeedback = styled('div')(({ theme }) => ({
130
- flex: '0 1 auto',
131
- paddingTop: theme.spacing(2),
132
- paddingLeft: 0,
133
- marginLeft: 0,
134
- marginRight: theme.spacing(1),
135
- }));
136
-
137
- const StyledFeedbackIcon = styled('div')(() => ({
138
- margin: 0,
139
- width: 'inherit',
140
- }));
141
-
142
- const StyledDeleteIcon = styled('div')(() => ({
143
- margin: 0,
144
- width: 'inherit',
145
- }));
146
-
147
- const StyledDelete = styled('div')(({ theme }) => ({
148
- flex: '0 1 auto',
149
- paddingTop: theme.spacing(2),
150
- paddingLeft: 0,
151
- marginLeft: 0,
152
- }));
153
-
154
- const StyledMiddleColumn = styled('div')(({ theme }) => ({
155
- display: 'flex',
156
- flex: 1,
157
- flexDirection: 'column',
158
- marginRight: theme.spacing(1),
159
- }));
160
-
161
- const StyledErrorText = styled('div')(({ theme }) => ({
162
- fontSize: theme.typography.fontSize - 2,
163
- color: theme.palette.error.main,
164
- }));
165
-
166
- export class ChoiceConfiguration extends React.Component {
167
- static propTypes = {
168
- noLabels: PropTypes.bool,
169
- useLetterOrdering: PropTypes.bool,
170
- className: PropTypes.string,
171
- error: PropTypes.string,
172
- mode: PropTypes.oneOf(['checkbox', 'radio']),
173
- defaultFeedback: PropTypes.object.isRequired,
174
- disabled: PropTypes.bool,
175
- nonEmpty: PropTypes.bool,
176
- data: PropTypes.shape({
177
- label: PropTypes.string.isRequired,
178
- value: PropTypes.string.isRequired,
179
- correct: PropTypes.bool,
180
- feedback: PropTypes.shape({
181
- type: PropTypes.string,
182
- value: PropTypes.string,
183
- }),
184
- }),
185
- onDelete: PropTypes.func,
186
- onChange: PropTypes.func,
187
- index: PropTypes.number,
188
- imageSupport: PropTypes.shape({
189
- add: PropTypes.func.isRequired,
190
- delete: PropTypes.func.isRequired,
191
- }),
192
- disableImageAlignmentButtons: PropTypes.bool,
193
- allowFeedBack: PropTypes.bool,
194
- allowDelete: PropTypes.bool,
195
- noCorrectAnswerError: PropTypes.string,
196
- spellCheck: PropTypes.bool,
197
- pluginOpts: PropTypes.object,
198
- toolbarOpts: PropTypes.object,
199
- uploadSoundSupport: PropTypes.object,
200
- maxImageWidth: PropTypes.number,
201
- maxImageHeight: PropTypes.number,
202
- };
203
-
204
- static defaultProps = {
205
- index: -1,
206
- noLabels: false,
207
- useLetterOrdering: false,
208
- allowFeedBack: true,
209
- allowDelete: true,
210
- };
211
-
212
- _changeFn = (key) => (update) => {
213
- const { data, onChange } = this.props;
214
-
215
- if (onChange) {
216
- onChange({ ...data, [key]: update });
217
- }
218
- };
219
-
220
- onLabelChange = this._changeFn('label');
221
-
222
- onCheckedChange = (event) => {
223
- const correct = event.target.checked;
224
- const { data, onChange } = this.props;
225
-
226
- if (onChange) {
227
- onChange({ ...data, correct });
228
- }
229
- };
230
-
231
- onFeedbackValueChange = (v) => {
232
- const { data, onChange } = this.props;
233
-
234
- if (data.feedback.type !== 'custom') {
235
- return;
236
- }
237
-
238
- const fb = { ...data.feedback, value: v };
239
-
240
- if (onChange) onChange({ ...data, feedback: fb });
241
- };
242
-
243
- onFeedbackTypeChange = (t) => {
244
- const { data, onChange } = this.props;
245
- const fb = { ...data.feedback, type: t };
246
-
247
- if (fb.type !== 'custom') {
248
- fb.value = undefined;
249
- }
250
-
251
- if (onChange) onChange({ ...data, feedback: fb });
252
- };
253
-
254
- render() {
255
- const {
256
- data,
257
- mode,
258
- onDelete,
259
- defaultFeedback,
260
- index,
261
- className,
262
- noLabels,
263
- useLetterOrdering,
264
- imageSupport,
265
- disableImageAlignmentButtons,
266
- disabled,
267
- spellCheck,
268
- nonEmpty,
269
- allowFeedBack,
270
- allowDelete,
271
- pluginOpts,
272
- toolbarOpts,
273
- error,
274
- noCorrectAnswerError,
275
- uploadSoundSupport,
276
- maxImageWidth,
277
- maxImageHeight,
278
- mathMlOptions = {},
279
- } = this.props;
280
-
281
- const InputToggle = mode === 'checkbox' ? InputCheckbox : InputRadio;
282
-
283
- return (
284
- <StyledTopRow>
285
- {index > 0 && (
286
- <StyledIndex type="title">
287
- {useLetterOrdering ? String.fromCharCode(96 + index).toUpperCase() : index}
288
- </StyledIndex>
289
- )}
290
-
291
- <StyledToggle>
292
- <InputToggle
293
- onChange={this.onCheckedChange}
294
- label={!noLabels ? 'Correct' : ''}
295
- checked={!!data.correct}
296
- error={noCorrectAnswerError}
297
- />
298
- </StyledToggle>
299
-
300
- <StyledMiddleColumn>
301
- <EditableHtmlContainer
302
- label={!noLabels ? 'Label' : ''}
303
- value={data.label}
304
- onChange={this.onLabelChange}
305
- imageSupport={imageSupport}
306
- disableImageAlignmentButtons={disableImageAlignmentButtons}
307
- disabled={disabled}
308
- spellCheck={spellCheck}
309
- nonEmpty={nonEmpty}
310
- pluginOpts={pluginOpts}
311
- toolbarOpts={toolbarOpts}
312
- error={error}
313
- uploadSoundSupport={uploadSoundSupport}
314
- mathMlOptions={mathMlOptions}
315
- maxImageWidth={maxImageWidth}
316
- maxImageHeight={maxImageHeight}
317
- />
318
- {error && <StyledErrorText>{error}</StyledErrorText>}
319
-
320
- {allowFeedBack && (
321
- <Feedback
322
- {...data.feedback}
323
- correct={data.correct}
324
- defaults={defaultFeedback}
325
- onChange={this.onFeedbackValueChange}
326
- toolbarOpts={toolbarOpts}
327
- />
328
- )}
329
- </StyledMiddleColumn>
330
-
331
- {allowFeedBack && (
332
- <StyledFeedback>
333
- <InputContainer label={!noLabels ? 'Feedback' : ''}>
334
- <StyledFeedbackIcon>
335
- <FeedbackMenu onChange={this.onFeedbackTypeChange} value={data.feedback} />
336
- </StyledFeedbackIcon>
337
- </InputContainer>
338
- </StyledFeedback>
339
- )}
340
-
341
- {allowDelete && (
342
- <StyledDelete>
343
- <InputContainer label={!noLabels ? 'Delete' : ''}>
344
- <StyledDeleteIcon>
345
- <IconButton aria-label="delete" onClick={onDelete} size="large">
346
- <ActionDelete />
347
- </IconButton>
348
- </StyledDeleteIcon>
349
- </InputContainer>
350
- </StyledDelete>
351
- )}
352
- </StyledTopRow>
353
- );
354
- }
355
- }
356
-
357
- export default ChoiceConfiguration;
@@ -1,30 +0,0 @@
1
- import { includes } from 'lodash-es';
2
-
3
- /**
4
- * Add value to every model.choices.
5
- * @param {Object} model the model to normalize
6
- * @return {Object} the updated model
7
- */
8
- export const normalizeChoices = (model) => {
9
- const choices = model.choices.map((c, index) => {
10
- if (!c.value) {
11
- c.value = `${index}`;
12
- }
13
- return c;
14
- });
15
- return { ...model, choices };
16
- };
17
-
18
- /**
19
- * Find the first available index.
20
- * @param {string[]} values
21
- * @param {number} index
22
- * @return {string}
23
- */
24
- export const firstAvailableIndex = (values, index) => {
25
- if (includes(values, `${index}`)) {
26
- return firstAvailableIndex(values, index + 1);
27
- } else {
28
- return `${index}`;
29
- }
30
- };