@pie-lib/mask-markup 1.13.47-next.1 → 1.15.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 (76) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/NEXT.CHANGELOG.json +1 -0
  3. package/lib/__tests__/drag-in-the-blank.test.js +71 -0
  4. package/lib/__tests__/index.test.js +50 -0
  5. package/lib/__tests__/mask.test.js +149 -0
  6. package/lib/__tests__/serialization.test.js +45 -0
  7. package/lib/__tests__/utils.js +17 -0
  8. package/lib/__tests__/with-mask.test.js +65 -0
  9. package/lib/choices/__tests__/index.test.js +85 -0
  10. package/lib/choices/choice.js +81 -18
  11. package/lib/choices/index.js +12 -4
  12. package/lib/componentize.js +1 -1
  13. package/lib/components/__tests__/blank.test.js +234 -0
  14. package/lib/components/__tests__/correct-input.test.js +63 -0
  15. package/lib/components/__tests__/dropdown.test.js +70 -0
  16. package/lib/components/__tests__/input.test.js +64 -0
  17. package/lib/components/blank.js +147 -35
  18. package/lib/components/correct-input.js +9 -4
  19. package/lib/components/dropdown.js +183 -50
  20. package/lib/components/input.js +1 -1
  21. package/lib/constructed-response.js +88 -24
  22. package/lib/customizable.js +48 -0
  23. package/lib/drag-in-the-blank.js +35 -9
  24. package/lib/index.js +9 -1
  25. package/lib/inline-dropdown.js +4 -2
  26. package/lib/mask.js +46 -7
  27. package/lib/serialization.js +1 -1
  28. package/lib/with-mask.js +35 -3
  29. package/package.json +5 -5
  30. package/src/__tests__/__snapshots__/drag-in-the-blank.test.js.snap +316 -0
  31. package/src/__tests__/__snapshots__/mask.test.js.snap +55 -0
  32. package/src/__tests__/__snapshots__/with-mask.test.js.snap +62 -0
  33. package/src/__tests__/drag-in-the-blank.test.js +71 -0
  34. package/src/__tests__/index.test.js +39 -0
  35. package/src/__tests__/mask.test.js +152 -0
  36. package/src/__tests__/serialization.test.js +54 -0
  37. package/src/__tests__/utils.js +1 -0
  38. package/src/__tests__/with-mask.test.js +51 -0
  39. package/src/choices/__tests__/__snapshots__/index.test.js.snap +209 -0
  40. package/src/choices/__tests__/index.test.js +62 -0
  41. package/src/choices/choice.jsx +60 -6
  42. package/src/choices/index.jsx +2 -2
  43. package/src/components/__tests__/__snapshots__/blank.test.js.snap +111 -0
  44. package/src/components/__tests__/__snapshots__/correct-input.test.js.snap +64 -0
  45. package/src/components/__tests__/__snapshots__/dropdown.test.js.snap +133 -0
  46. package/src/components/__tests__/__snapshots__/input.test.js.snap +34 -0
  47. package/src/components/__tests__/blank.test.js +202 -0
  48. package/src/components/__tests__/correct-input.test.js +49 -0
  49. package/src/components/__tests__/dropdown.test.js +51 -0
  50. package/src/components/__tests__/input.test.js +50 -0
  51. package/src/components/blank.jsx +139 -28
  52. package/src/components/correct-input.jsx +6 -1
  53. package/src/components/dropdown.jsx +192 -71
  54. package/src/constructed-response.jsx +76 -18
  55. package/src/customizable.jsx +35 -0
  56. package/src/drag-in-the-blank.jsx +26 -3
  57. package/src/index.js +10 -1
  58. package/src/inline-dropdown.jsx +2 -0
  59. package/src/mask.jsx +30 -5
  60. package/src/serialization.js +1 -1
  61. package/src/with-mask.jsx +39 -2
  62. package/README.md +0 -14
  63. package/lib/choices/choice.js.map +0 -1
  64. package/lib/choices/index.js.map +0 -1
  65. package/lib/componentize.js.map +0 -1
  66. package/lib/components/blank.js.map +0 -1
  67. package/lib/components/correct-input.js.map +0 -1
  68. package/lib/components/dropdown.js.map +0 -1
  69. package/lib/components/input.js.map +0 -1
  70. package/lib/constructed-response.js.map +0 -1
  71. package/lib/drag-in-the-blank.js.map +0 -1
  72. package/lib/index.js.map +0 -1
  73. package/lib/inline-dropdown.js.map +0 -1
  74. package/lib/mask.js.map +0 -1
  75. package/lib/serialization.js.map +0 -1
  76. package/lib/with-mask.js.map +0 -1
@@ -1,3 +1,4 @@
1
+ import grey from '@material-ui/core/colors/grey';
1
2
  import React from 'react';
2
3
  import ReactDOM from 'react-dom';
3
4
  import PropTypes from 'prop-types';
@@ -8,6 +9,7 @@ import { withStyles } from '@material-ui/core/styles';
8
9
  import Chip from '@material-ui/core/Chip';
9
10
  import classnames from 'classnames';
10
11
  import { color } from '@pie-lib/render-ui';
12
+
11
13
  const log = debug('pie-lib:mask-markup:blank');
12
14
  export const DRAG_TYPE = 'MaskBlank';
13
15
 
@@ -17,20 +19,19 @@ const useStyles = withStyles(() => ({
17
19
  minWidth: '200px',
18
20
  touchAction: 'none',
19
21
  overflow: 'hidden',
22
+ whiteSpace: 'nowrap', // Prevent line wrapping
20
23
  },
21
24
  chip: {
22
25
  backgroundColor: color.background(),
23
- border: `1px solid ${color.text()}`,
26
+ border: `2px dashed ${color.text()}`,
24
27
  color: color.text(),
25
- minWidth: '90px',
26
28
  fontSize: 'inherit',
27
- minHeight: '32px',
28
- height: 'auto',
29
29
  maxWidth: '374px',
30
30
  position: 'relative',
31
+ borderRadius: '3px',
31
32
  },
32
33
  chipLabel: {
33
- whiteSpace: 'pre-wrap',
34
+ whiteSpace: 'normal',
34
35
  // Added for touch devices, for image content.
35
36
  // This will prevent the context menu from appearing and not allowing other interactions with the image.
36
37
  // If interactions with the image in the token will be requested we should handle only the context Menu.
@@ -39,6 +40,16 @@ const useStyles = withStyles(() => ({
39
40
  display: 'block',
40
41
  padding: '2px 0',
41
42
  },
43
+ // Remove default <p> margins to ensure consistent spacing across all wrapped content (p, span, div, math)
44
+ // Padding for top and bottom will instead be controlled by the container for consistent layout
45
+ // Ensures consistent behavior with pie-api-browser, where marginTop is already removed by a Bootstrap stylesheet
46
+ '& p': {
47
+ marginTop: '0',
48
+ marginBottom: '0',
49
+ },
50
+ '& mjx-frac': {
51
+ fontSize: '120% !important',
52
+ },
42
53
  },
43
54
  hidden: {
44
55
  color: 'transparent',
@@ -59,28 +70,44 @@ const useStyles = withStyles(() => ({
59
70
  whiteSpace: 'nowrap',
60
71
  overflow: 'hidden',
61
72
  },
73
+ parentOver: {
74
+ border: `1px solid ${grey[500]}`,
75
+ backgroundColor: `${grey[300]}`,
76
+ },
62
77
  }));
63
78
 
64
79
  export class BlankContent extends React.Component {
65
- static propTypes = {
66
- id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
67
- disabled: PropTypes.bool,
68
- duplicates: PropTypes.bool,
69
- choice: PropTypes.object,
70
- classes: PropTypes.object,
71
- isOver: PropTypes.bool,
72
- dragItem: PropTypes.object,
73
- correct: PropTypes.bool,
74
- onChange: PropTypes.func,
75
- };
76
-
77
80
  constructor() {
78
81
  super();
79
82
  this.state = {
80
83
  height: 0,
84
+ width: 0,
81
85
  };
82
86
  }
83
87
 
88
+ handleImageLoad = () => {
89
+ this.updateDimensions();
90
+ };
91
+
92
+ handleElements() {
93
+ const imageElement = this.spanRef?.querySelector('img');
94
+
95
+ if (imageElement) {
96
+ imageElement.onload = this.handleImageLoad;
97
+ } else {
98
+ setTimeout(() => {
99
+ this.updateDimensions();
100
+ }, 300);
101
+ }
102
+ }
103
+
104
+ componentDidMount() {
105
+ this.handleElements();
106
+ if (this.rootRef) {
107
+ this.rootRef.addEventListener('touchstart', this.handleTouchStart, { passive: false });
108
+ }
109
+ }
110
+
84
111
  componentDidUpdate(prevProps) {
85
112
  renderMath(this.rootRef);
86
113
  const { choice: currentChoice } = this.props;
@@ -90,14 +117,59 @@ export class BlankContent extends React.Component {
90
117
  if (!currentChoice) {
91
118
  this.setState({
92
119
  height: 0,
120
+ width: 0,
93
121
  });
94
122
  return;
95
123
  }
96
- setTimeout(() => {
97
- this.setState({
98
- height: this.spanRef.offsetHeight,
99
- });
100
- }, 300);
124
+ this.handleElements();
125
+ }
126
+ }
127
+
128
+ componentWillUnmount() {
129
+ if (this.rootRef) {
130
+ this.rootRef.removeEventListener('touchstart', this.handleTouchStart);
131
+ }
132
+ }
133
+
134
+ handleTouchStart = (e) => {
135
+ e.preventDefault();
136
+ this.touchStartTimer = setTimeout(() => {
137
+ this.startDrag();
138
+ }, 300); // Start drag after 300ms (touch and hold duration)
139
+ };
140
+
141
+ startDrag = () => {
142
+ const { connectDragSource, disabled } = this.props;
143
+ if (!disabled) {
144
+ connectDragSource(this.rootRef);
145
+ }
146
+ };
147
+
148
+ updateDimensions() {
149
+ if (this.spanRef && this.rootRef) {
150
+ // Temporarily set rootRef width to 'auto' for natural measurement
151
+ this.rootRef.style.width = 'auto';
152
+
153
+ // Get the natural dimensions of the content
154
+ const width = this.spanRef.offsetWidth || 0;
155
+ const height = this.spanRef.offsetHeight || 0;
156
+
157
+ const widthWithPadding = width + 24; // 12px padding on each side
158
+ const heightWithPadding = height + 24; // 12px padding on top and bottom
159
+
160
+ const responseAreaWidth = parseFloat(this.props.emptyResponseAreaWidth) || 0;
161
+ const responseAreaHeight = parseFloat(this.props.emptyResponseAreaHeight) || 0;
162
+
163
+ const adjustedWidth = widthWithPadding <= responseAreaWidth ? responseAreaWidth : widthWithPadding;
164
+ const adjustedHeight = heightWithPadding <= responseAreaHeight ? responseAreaHeight : heightWithPadding;
165
+
166
+ this.setState((prevState) => ({
167
+ width: adjustedWidth > responseAreaWidth ? adjustedWidth : prevState.width,
168
+ height: adjustedHeight > responseAreaHeight ? adjustedHeight : prevState.height,
169
+ }));
170
+
171
+ this.rootRef.style.width = `${adjustedWidth}px`;
172
+ this.rootRef.style.height = `${adjustedHeight}px`;
101
173
  }
102
174
  }
103
175
 
@@ -109,6 +181,29 @@ export class BlankContent extends React.Component {
109
181
  });
110
182
  }
111
183
 
184
+ getRootDimensions() {
185
+ // Handle potential non-numeric values
186
+ const responseAreaWidth = !isNaN(parseFloat(this.props.emptyResponseAreaWidth))
187
+ ? parseFloat(this.props.emptyResponseAreaWidth)
188
+ : 0;
189
+ const responseAreaHeight = !isNaN(parseFloat(this.props.emptyResponseAreaHeight))
190
+ ? parseFloat(this.props.emptyResponseAreaHeight)
191
+ : 0;
192
+
193
+ const rootStyle = {
194
+ height: this.state.height || responseAreaHeight,
195
+ width: this.state.width || responseAreaWidth,
196
+ };
197
+
198
+ // add minWidth, minHeight if width and height are not defined
199
+ // minWidth, minHeight will be also in model in the future
200
+ return {
201
+ ...rootStyle,
202
+ ...(responseAreaWidth ? {} : { minWidth: 90 }),
203
+ ...(responseAreaHeight ? {} : { minHeight: 32 }),
204
+ };
205
+ }
206
+
112
207
  render() {
113
208
  const { disabled, choice, classes, isOver, dragItem, correct } = this.props;
114
209
  const draggedLabel = dragItem && isOver && dragItem.choice.value;
@@ -158,22 +253,38 @@ export class BlankContent extends React.Component {
158
253
  )}
159
254
  </React.Fragment>
160
255
  }
161
- className={classnames(classes.chip, isOver && classes.over, {
256
+ className={classnames(classes.chip, isOver && classes.over, isOver && classes.parentOver, {
162
257
  [classes.correct]: correct !== undefined && correct,
163
258
  [classes.incorrect]: correct !== undefined && !correct,
164
259
  })}
165
260
  variant={disabled ? 'outlined' : undefined}
166
261
  style={{
167
- ...(this.state.height ? { height: this.state.height } : {}),
168
- }}
169
- classes={{
170
- label: isOver && classes.over,
262
+ ...this.getRootDimensions(),
171
263
  }}
172
264
  />
173
265
  );
174
266
  }
175
267
  }
176
268
 
269
+ BlankContent.defaultProps = {
270
+ emptyResponseAreaWidth: 0,
271
+ emptyResponseAreaHeight: 0,
272
+ };
273
+
274
+ BlankContent.propTypes = {
275
+ id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
276
+ disabled: PropTypes.bool,
277
+ duplicates: PropTypes.bool,
278
+ choice: PropTypes.object,
279
+ classes: PropTypes.object,
280
+ isOver: PropTypes.bool,
281
+ dragItem: PropTypes.object,
282
+ correct: PropTypes.bool,
283
+ onChange: PropTypes.func,
284
+ emptyResponseAreaWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
285
+ emptyResponseAreaHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
286
+ };
287
+
177
288
  const StyledBlankContent = useStyles(BlankContent);
178
289
 
179
290
  const connectedBlankContent = useStyles(({ connectDragSource, connectDropTarget, ...props }) => {
@@ -231,7 +342,7 @@ const tileSource = {
231
342
  // this will be null if it did not drop
232
343
  const dropResult = monitor.getDropResult();
233
344
 
234
- if (!dropResult || (dropResult.dropped && !props.duplicates)) {
345
+ if (!dropResult || dropResult.dropped) {
235
346
  const draggedItem = monitor.getItem();
236
347
 
237
348
  if (draggedItem.fromChoice) {
@@ -37,6 +37,8 @@ export default withStyles(() => ({
37
37
  incorrect: correctStyle(color.incorrect()),
38
38
  box: {
39
39
  fontSize: 'inherit',
40
+ display: 'inline-block',
41
+ verticalAlign: 'middle',
40
42
  },
41
43
  outlinedInput: {
42
44
  padding: '2px',
@@ -60,8 +62,11 @@ export default withStyles(() => ({
60
62
  spellCheck,
61
63
  ...rest
62
64
  } = props;
65
+
63
66
  const label = typeof correct === 'boolean' ? (correct ? 'correct' : 'incorrect') : undefined;
64
- const inputProps = charactersLimit ? { maxLength: charactersLimit } : {};
67
+ const inputProps = charactersLimit
68
+ ? { maxLength: charactersLimit, 'aria-label': 'Enter answer' }
69
+ : { 'aria-label': 'Enter answer' };
65
70
 
66
71
  if (width) {
67
72
  inputProps.style = {
@@ -1,10 +1,17 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import Select from '@material-ui/core/Select';
3
+ import Button from '@material-ui/core/Button';
4
+ import InputLabel from '@material-ui/core/InputLabel';
5
+ import Menu from '@material-ui/core/Menu';
4
6
  import MenuItem from '@material-ui/core/MenuItem';
5
- import CorrectInput from './correct-input';
7
+ import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
8
+ import Close from '@material-ui/icons/Close';
9
+ import Check from '@material-ui/icons/Check';
6
10
  import { withStyles } from '@material-ui/core/styles';
11
+ import classNames from 'classnames';
12
+
7
13
  import { color } from '@pie-lib/render-ui';
14
+ import { renderMath } from '@pie-lib/math-rendering';
8
15
 
9
16
  class Dropdown extends React.Component {
10
17
  static propTypes = {
@@ -22,73 +29,148 @@ class Dropdown extends React.Component {
22
29
  super(props);
23
30
 
24
31
  this.state = {
25
- showCheckmark: false,
26
- open: false,
32
+ anchorEl: null,
33
+ highlightedOptionId: null,
27
34
  };
35
+
36
+ this.elementRefs = [];
28
37
  }
29
38
 
30
- showCheckmarkAndOpen = () => {
31
- this.setState({
32
- showCheckmark: true,
33
- open: true,
39
+ componentDidUpdate() {
40
+ this.elementRefs.forEach((ref) => {
41
+ if (ref) {
42
+ renderMath(ref);
43
+ }
34
44
  });
45
+ }
46
+
47
+ handleClick = (event) => this.setState({ anchorEl: event.currentTarget });
48
+
49
+ handleClose = () => this.setState({ anchorEl: null });
50
+
51
+ handleHighlight = (index) => {
52
+ const highlightedOptionId = `dropdown-option-${this.props.id}-${index}`;
53
+
54
+ this.setState({ highlightedOptionId });
35
55
  };
36
56
 
37
- hideCheckmarkAndClose = () => {
38
- this.setState({
39
- showCheckmark: false,
40
- open: false,
41
- });
57
+ handleSelect = (value, index) => {
58
+ this.props.onChange(this.props.id, value);
59
+ this.handleHighlight(index);
60
+ this.handleClose();
42
61
  };
43
62
 
63
+ getLabel(choices, value) {
64
+ const found = (choices || []).find((choice) => choice.value === value);
65
+
66
+ return found ? found.label.trim() : undefined;
67
+ }
68
+
44
69
  render() {
45
- const { classes, id, correct, disabled, value, onChange, choices, showCorrectAnswer } = this.props;
70
+ const { classes, id, correct, disabled, value, choices, showCorrectAnswer, singleQuery, correctValue } = this.props;
71
+
72
+ const { anchorEl } = this.state;
73
+ const open = Boolean(anchorEl);
74
+ const buttonId = `dropdown-button-${id}`;
75
+ const menuId = `dropdown-menu-${id}`;
76
+ const valueDisplayId = `dropdown-value-${id}`;
77
+
78
+ // Determine the class for disabled state, view mode and evaluate mode
79
+ let disabledClass;
80
+ // Reset elementRefs before each render to avoid stale references
81
+ this.elementRefs = [];
82
+
83
+ if (disabled && correct !== undefined) {
84
+ disabledClass = correct || showCorrectAnswer ? classes.disabledCorrect : classes.disabledIncorrect;
85
+ }
86
+
87
+ // Create distinct, visually hidden labels for each dropdown
88
+ const incrementedId = parseInt(id, 10) + 1;
89
+ const labelId = singleQuery ? 'Query-label' : `Query-label-${incrementedId}`;
90
+ const labelText = singleQuery ? 'Query' : `Query ${incrementedId}`;
91
+
92
+ // Changed from Select to Button for dropdown to enhance accessibility. This modification offers explicit control over aria attributes and focuses management, ensuring the dropdown is compliant with accessibility standards. The use of Button and Menu components allows for better handling of keyboard interactions and provides accessible labels and menus, aligning with WCAG guidelines and improving usability for assistive technology users.
46
93
 
47
- const { showCheckmark, open } = this.state;
94
+ let correctnessIcon = null;
95
+ if (disabled && correct !== undefined) {
96
+ correctnessIcon =
97
+ correct || showCorrectAnswer ? (
98
+ <Check className={classNames(classes.correctnessIndicatorIcon, classes.correctIcon)} />
99
+ ) : (
100
+ <Close className={classNames(classes.correctnessIndicatorIcon, classes.incorrectIcon)} />
101
+ );
102
+ }
48
103
 
49
104
  return (
50
- <Select
51
- classes={{
52
- root: classes.root,
53
- icon: classes.icon,
54
- selectMenu: classes.selectMenu,
55
- select: classes.select,
56
- }}
57
- disabled={disabled}
58
- value={value || ''}
59
- onOpen={this.showCheckmarkAndOpen}
60
- onClose={this.hideCheckmarkAndClose}
61
- open={open}
62
- input={<CorrectInput correct={showCorrectAnswer || correct} />}
63
- MenuProps={{
64
- keepMounted: true,
65
- disablePortal: true,
66
- }}
67
- onChange={(e) => {
68
- onChange(id, e.target.value);
69
- }}
70
- >
71
- {(choices || []).map((c, index) => (
72
- <MenuItem
73
- classes={{ root: classes.menuRoot, selected: classes.selected }}
74
- key={`${c.label}-${index}`}
75
- value={c.value}
76
- >
77
- <span
78
- className={classes.label}
79
- dangerouslySetInnerHTML={{
80
- __html: c.label,
81
- }}
82
- />
83
- {showCheckmark && (
84
- <span
85
- className={classes.label}
86
- dangerouslySetInnerHTML={{ __html: c.value === value ? ' &check;' : '' }}
87
- />
88
- )}
89
- </MenuItem>
90
- ))}
91
- </Select>
105
+ <>
106
+ <InputLabel className={classes.srOnly} id={labelId}>
107
+ {labelText}
108
+ </InputLabel>
109
+ <Button
110
+ aria-controls={open ? menuId : undefined}
111
+ aria-haspopup="listbox"
112
+ aria-expanded={open ? 'true' : undefined}
113
+ aria-activedescendant={this.state.highlightedOptionId}
114
+ onClick={this.handleClick}
115
+ classes={{
116
+ root: classes.root,
117
+ disabled: disabledClass,
118
+ }}
119
+ disabled={disabled}
120
+ id={buttonId}
121
+ role="combobox"
122
+ aria-label="Select answer"
123
+ aria-labelledby={valueDisplayId}
124
+ >
125
+ {correctnessIcon}
126
+ <span
127
+ id={valueDisplayId}
128
+ className={classes.label}
129
+ dangerouslySetInnerHTML={{
130
+ __html: correctValue ? correctValue : this.getLabel(choices, value) ? this.getLabel(choices, value) : '',
131
+ }}
132
+ />
133
+ <ArrowDropDownIcon />
134
+ </Button>
135
+ <Menu
136
+ id={menuId}
137
+ anchorEl={anchorEl}
138
+ className={classes.selectMenu}
139
+ keepMounted
140
+ open={open}
141
+ onClose={this.handleClose}
142
+ MenuListProps={{
143
+ 'aria-labelledby': buttonId,
144
+ role: 'listbox',
145
+ }}
146
+ >
147
+ {(choices || []).map((c, index) => {
148
+ const optionId = `dropdown-option-${id}-${index}`;
149
+
150
+ return (
151
+ <MenuItem
152
+ id={optionId}
153
+ classes={{ root: classes.menuRoot, selected: classes.selected }}
154
+ key={`${c.label}-${index}`}
155
+ value={c.value}
156
+ onClick={() => this.handleSelect(c.value, index)}
157
+ role="option"
158
+ aria-selected={this.state.highlightedOptionId === optionId ? 'true' : undefined}
159
+ >
160
+ <span
161
+ ref={(ref) => (this.elementRefs[index] = ref)}
162
+ className={classes.label}
163
+ dangerouslySetInnerHTML={{ __html: c.label }}
164
+ />
165
+ <span
166
+ className={classes.label}
167
+ dangerouslySetInnerHTML={{ __html: c.value === value ? ' &check;' : '' }}
168
+ />
169
+ </MenuItem>
170
+ );
171
+ })}
172
+ </Menu>
173
+ </>
92
174
  );
93
175
  }
94
176
  }
@@ -96,34 +178,49 @@ class Dropdown extends React.Component {
96
178
  const styles = () => ({
97
179
  root: {
98
180
  color: color.text(),
181
+ border: `1px solid ${color.text()}`,
182
+ borderRadius: '4px',
183
+ justifyContent: 'space-between',
99
184
  backgroundColor: color.background(),
100
- borderColor: color.secondaryLight(),
101
- '& ul': {
102
- paddingTop: 0,
103
- paddingBottom: 0,
104
- border: `1px solid ${color.text()}`,
105
- borderRadius: '5px',
185
+ position: 'relative',
186
+ height: '45px',
187
+ width: 'fit-content',
188
+ margin: '2px',
189
+ textTransform: 'none',
190
+ '& span': {
191
+ paddingRight: '5px',
192
+ },
193
+ '& svg': {
194
+ position: 'absolute',
195
+ right: 0,
196
+ top: 'calc(50% - 12px)',
197
+ pointerEvents: 'none',
106
198
  color: color.text(),
107
- backgroundColor: color.background(),
199
+ marginLeft: '5px',
108
200
  },
109
201
  },
110
- select: {
111
- '&:focus': {
112
- borderRadius: '4px',
113
- },
202
+ disabledCorrect: {
203
+ borderWidth: '2px',
204
+ borderColor: color.correct(),
205
+ color: `${color.text()} !important`,
206
+ },
207
+ disabledIncorrect: {
208
+ borderWidth: '2px',
209
+ borderColor: color.incorrectWithIcon(),
210
+ color: `${color.text()} !important`,
114
211
  },
115
212
  selectMenu: {
116
213
  backgroundColor: color.background(),
214
+ border: `1px solid ${color.correct()} !important`,
117
215
  '&:hover': {
216
+ border: `1px solid ${color.text()} `,
118
217
  borderColor: 'initial',
119
218
  },
120
219
  '&:focus': {
220
+ border: `1px solid ${color.text()}`,
121
221
  borderColor: 'initial',
122
222
  },
123
223
  },
124
- icon: {
125
- color: color.text(),
126
- },
127
224
  selected: {
128
225
  color: `${color.text()} !important`,
129
226
  backgroundColor: `${color.background()} !important`,
@@ -155,6 +252,30 @@ const styles = () => ({
155
252
  label: {
156
253
  fontSize: 'max(1rem, 14px)',
157
254
  },
255
+ srOnly: {
256
+ position: 'absolute',
257
+ left: '-10000px',
258
+ top: 'auto',
259
+ width: '1px',
260
+ height: '1px',
261
+ overflow: 'hidden',
262
+ },
263
+ correctnessIndicatorIcon: {
264
+ color: `${color.white()} !important`,
265
+ position: 'absolute',
266
+ top: '-8px !important',
267
+ left: '-8px',
268
+ marginLeft: '0 !important',
269
+ borderRadius: '50%',
270
+ fontSize: '16px',
271
+ padding: '2px',
272
+ },
273
+ correctIcon: {
274
+ backgroundColor: color.correct(),
275
+ },
276
+ incorrectIcon: {
277
+ backgroundColor: color.incorrectWithIcon(),
278
+ },
158
279
  });
159
280
 
160
281
  export default withStyles(styles)(Dropdown);