@pie-lib/mask-markup 1.29.3-next.2 → 1.30.0-mui-update.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 (40) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/choices/choice.js +74 -203
  3. package/lib/choices/choice.js.map +1 -1
  4. package/lib/choices/index.js +19 -52
  5. package/lib/choices/index.js.map +1 -1
  6. package/lib/componentize.js +1 -5
  7. package/lib/componentize.js.map +1 -1
  8. package/lib/components/blank.js +292 -357
  9. package/lib/components/blank.js.map +1 -1
  10. package/lib/components/correct-input.js +41 -65
  11. package/lib/components/correct-input.js.map +1 -1
  12. package/lib/components/dropdown.js +203 -248
  13. package/lib/components/dropdown.js.map +1 -1
  14. package/lib/components/input.js +10 -17
  15. package/lib/components/input.js.map +1 -1
  16. package/lib/constructed-response.js +38 -52
  17. package/lib/constructed-response.js.map +1 -1
  18. package/lib/customizable.js +5 -9
  19. package/lib/customizable.js.map +1 -1
  20. package/lib/drag-in-the-blank.js +117 -96
  21. package/lib/drag-in-the-blank.js.map +1 -1
  22. package/lib/index.js +0 -7
  23. package/lib/index.js.map +1 -1
  24. package/lib/inline-dropdown.js +4 -12
  25. package/lib/inline-dropdown.js.map +1 -1
  26. package/lib/mask.js +40 -112
  27. package/lib/mask.js.map +1 -1
  28. package/lib/serialization.js +8 -48
  29. package/lib/serialization.js.map +1 -1
  30. package/lib/with-mask.js +26 -55
  31. package/lib/with-mask.js.map +1 -1
  32. package/package.json +12 -10
  33. package/src/choices/choice.jsx +58 -154
  34. package/src/choices/index.jsx +8 -2
  35. package/src/components/blank.jsx +272 -262
  36. package/src/components/correct-input.jsx +33 -39
  37. package/src/components/dropdown.jsx +165 -156
  38. package/src/constructed-response.jsx +22 -18
  39. package/src/drag-in-the-blank.jsx +97 -39
  40. package/src/mask.jsx +18 -27
@@ -1,13 +1,13 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { renderMath } from '@pie-lib/math-rendering';
4
+ import { DragProvider } from '@pie-lib/drag';
4
5
  import Choices from './choices';
5
6
  import Blank from './components/blank';
6
7
  import { withMask } from './with-mask';
7
8
 
8
- // eslint-disable-next-line react/display-name
9
9
  const Masked = withMask('blank', (props) => (node, data, onChange) => {
10
- const dataset = node.data ? node.data.dataset || {} : {};
10
+ const dataset = node.data?.dataset || {};
11
11
  if (dataset.component === 'blank') {
12
12
  // eslint-disable-next-line react/prop-types
13
13
  const {
@@ -18,6 +18,7 @@ const Masked = withMask('blank', (props) => (node, data, onChange) => {
18
18
  showCorrectAnswer,
19
19
  emptyResponseAreaWidth,
20
20
  emptyResponseAreaHeight,
21
+ instanceId,
21
22
  } = props;
22
23
  const choiceId = showCorrectAnswer ? correctResponse[dataset.id] : data[dataset.id];
23
24
  // eslint-disable-next-line react/prop-types
@@ -33,7 +34,16 @@ const Masked = withMask('blank', (props) => (node, data, onChange) => {
33
34
  id={dataset.id}
34
35
  emptyResponseAreaWidth={emptyResponseAreaWidth}
35
36
  emptyResponseAreaHeight={emptyResponseAreaHeight}
36
- onChange={onChange}
37
+ onChange={(id, choiceId) => {
38
+ const newData = { ...data };
39
+ if (choiceId === undefined) {
40
+ delete newData[id];
41
+ } else {
42
+ newData[id] = choiceId;
43
+ }
44
+ onChange(newData);
45
+ }}
46
+ instanceId={instanceId}
37
47
  />
38
48
  );
39
49
  }
@@ -44,7 +54,7 @@ export default class DragInTheBlank extends React.Component {
44
54
  markup: PropTypes.string,
45
55
  layout: PropTypes.object,
46
56
  choicesPosition: PropTypes.string,
47
- choices: PropTypes.arrayOf(PropTypes.shape({ label: PropTypes.string, value: PropTypes.string })),
57
+ choices: PropTypes.array,
48
58
  value: PropTypes.object,
49
59
  onChange: PropTypes.func,
50
60
  duplicates: PropTypes.bool,
@@ -54,16 +64,63 @@ export default class DragInTheBlank extends React.Component {
54
64
  showCorrectAnswer: PropTypes.bool,
55
65
  emptyResponseAreaWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
56
66
  emptyResponseAreaHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
67
+ instanceId: PropTypes.string,
57
68
  };
58
69
 
59
- UNSAFE_componentWillReceiveProps() {
60
- if (this.rootRef) {
61
- renderMath(this.rootRef);
70
+ static defaultProps = {
71
+ instanceId: 'drag-in-the-blank',
72
+ };
73
+
74
+ handleDragEnd = (event) => {
75
+ console.log('Drag End Event:', event);
76
+ const { active, over } = event;
77
+ const { onChange, value } = this.props;
78
+
79
+ if (!over || !active || !onChange) {
80
+ console.log('Early return - missing data:', { over: !!over, active: !!active, onChange: !!onChange });
81
+ return;
62
82
  }
63
- }
83
+
84
+ const draggedData = active.data.current;
85
+ const dropData = over.data.current;
86
+
87
+ console.log('Drag data:', draggedData);
88
+ console.log('Drop data:', dropData);
89
+
90
+ // Handle drop from choice to blank or blank to blank
91
+ if (draggedData?.type === 'MaskBlank' && dropData?.accepts?.includes('MaskBlank')) {
92
+ console.log('Valid drag/drop types');
93
+ const draggedItem = draggedData;
94
+ const targetId = dropData.id;
95
+
96
+ if (draggedItem.instanceId === dropData.instanceId) {
97
+ console.log('Instance IDs match');
98
+
99
+ // Handle drop from choice to blank
100
+ if (draggedItem.fromChoice === true) {
101
+ console.log('Dropping from choice to blank:', targetId);
102
+ const newValue = { ...value };
103
+ newValue[targetId] = draggedItem.choice.id;
104
+ onChange(newValue);
105
+ }
106
+ // Handle drop from blank to blank
107
+ else if (draggedItem.id !== targetId) {
108
+ console.log('Moving from blank to blank:', draggedItem.id, '->', targetId);
109
+ const newValue = { ...value };
110
+ newValue[targetId] = draggedItem.choice.id;
111
+ delete newValue[draggedItem.id];
112
+ onChange(newValue);
113
+ }
114
+ } else {
115
+ console.log('Instance ID mismatch:', draggedItem.instanceId, 'vs', dropData.instanceId);
116
+ }
117
+ } else {
118
+ console.log('Invalid drag/drop types:', draggedData?.type, dropData?.accepts);
119
+ }
120
+ };
64
121
 
65
122
  componentDidUpdate() {
66
- renderMath(this.rootRef);
123
+ if (this.rootRef) renderMath(this.rootRef);
67
124
  }
68
125
 
69
126
  getPositionDirection = (choicePosition) => {
@@ -97,7 +154,6 @@ export default class DragInTheBlank extends React.Component {
97
154
  const {
98
155
  markup,
99
156
  duplicates,
100
- layout,
101
157
  value,
102
158
  onChange,
103
159
  choicesPosition,
@@ -108,40 +164,42 @@ export default class DragInTheBlank extends React.Component {
108
164
  showCorrectAnswer,
109
165
  emptyResponseAreaWidth,
110
166
  emptyResponseAreaHeight,
167
+ layout,
168
+ instanceId
111
169
  } = this.props;
112
170
 
113
171
  const choicePosition = choicesPosition || 'below';
114
- const style = {
115
- display: 'flex',
116
- minWidth: '100px',
117
- ...this.getPositionDirection(choicePosition),
118
- };
172
+ const style = { display: 'flex', minWidth: '100px', ...this.getPositionDirection(choicePosition) };
119
173
 
120
174
  return (
121
- <div ref={(ref) => ref && (this.rootRef = ref)} style={style}>
122
- <Choices
123
- choicePosition={choicePosition}
124
- duplicates={duplicates}
125
- choices={choices}
126
- value={value}
127
- disabled={disabled}
128
- />
129
- <Masked
130
- elementType={'drag-in-the-blank'}
131
- markup={markup}
132
- layout={layout}
133
- value={value}
134
- choices={choices}
135
- onChange={onChange}
136
- disabled={disabled}
137
- duplicates={duplicates}
138
- feedback={feedback}
139
- correctResponse={correctResponse}
140
- showCorrectAnswer={showCorrectAnswer}
141
- emptyResponseAreaWidth={emptyResponseAreaWidth}
142
- emptyResponseAreaHeight={emptyResponseAreaHeight}
143
- />
144
- </div>
175
+ <DragProvider onDragEnd={this.handleDragEnd}>
176
+ <div ref={(ref) => (this.rootRef = ref)} style={style}>
177
+ <Choices
178
+ choicePosition={choicePosition}
179
+ choices={choices}
180
+ value={value}
181
+ duplicates={duplicates}
182
+ disabled={disabled}
183
+ instanceId={instanceId}
184
+ />
185
+ <Masked
186
+ elementType="drag-in-the-blank"
187
+ markup={markup}
188
+ layout={layout}
189
+ value={value}
190
+ choices={choices}
191
+ onChange={onChange}
192
+ disabled={disabled}
193
+ duplicates={duplicates}
194
+ feedback={feedback}
195
+ correctResponse={correctResponse}
196
+ showCorrectAnswer={showCorrectAnswer}
197
+ emptyResponseAreaWidth={emptyResponseAreaWidth}
198
+ emptyResponseAreaHeight={emptyResponseAreaHeight}
199
+ instanceId={instanceId}
200
+ />
201
+ </div>
202
+ </DragProvider>
145
203
  );
146
204
  }
147
205
  }
package/src/mask.jsx CHANGED
@@ -1,23 +1,18 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import get from 'lodash/get';
4
- import { withStyles } from '@material-ui/core/styles';
4
+ import { styled } from '@mui/material/styles';
5
5
  import { MARK_TAGS } from './serialization';
6
- import cx from 'classnames';
7
6
 
8
- const Paragraph = withStyles((theme) => ({
9
- para: {
10
- paddingTop: 2 * theme.spacing.unit,
11
- paddingBottom: 2 * theme.spacing.unit,
12
- },
13
- }))((props) => <div className={props.classes.para}>{props.children}</div>);
7
+ const Paragraph = styled('div')(({ theme }) => ({
8
+ paddingTop: theme.spacing(2),
9
+ paddingBottom: theme.spacing(2),
10
+ }));
14
11
 
15
- const Spacer = withStyles(() => ({
16
- spacer: {
17
- display: 'inline-block',
18
- width: '.75em',
19
- },
20
- }))((props) => <span className={props.classes.spacer} />);
12
+ const Spacer = styled('span')(() => ({
13
+ display: 'inline-block',
14
+ width: '.75em',
15
+ }));
21
16
 
22
17
  const restrictWhitespaceTypes = ['tbody', 'tr'];
23
18
 
@@ -120,21 +115,17 @@ export const renderChildren = (layout, value, onChange, rootRenderChildren, pare
120
115
  return children;
121
116
  };
122
117
 
123
- const MaskContainer = withStyles(() => ({
124
- main: {
125
- display: 'initial',
118
+ const MaskContainer = styled('div')(() => ({
119
+ display: 'initial',
120
+ '&:not(.MathJax) table': {
121
+ borderCollapse: 'collapse',
126
122
  },
127
- tableStyle: {
128
- '&:not(.MathJax) table': {
129
- borderCollapse: 'collapse',
130
- },
131
- // align table content to left as per STAR requirement PD-3687
132
- '&:not(.MathJax) table td, &:not(.MathJax) table th': {
133
- padding: '8px 12px',
134
- textAlign: 'left',
135
- },
123
+ // align table content to left as per STAR requirement PD-3687
124
+ '&:not(.MathJax) table td, &:not(.MathJax) table th': {
125
+ padding: '8px 12px',
126
+ textAlign: 'left',
136
127
  },
137
- }))((props) => <div className={cx(props.classes.main, props.classes.tableStyle)}>{props.children}</div>);
128
+ }));
138
129
 
139
130
  /**
140
131
  * Renders a layout that uses the slate.js Value model structure.