@pie-element/image-cloze-association 10.1.2-next.2 → 10.1.2

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 (130) hide show
  1. package/CHANGELOG.json +437 -0
  2. package/CHANGELOG.md +1997 -0
  3. package/LICENSE.md +5 -0
  4. package/README.md +1 -0
  5. package/configure/CHANGELOG.json +197 -0
  6. package/configure/CHANGELOG.md +1600 -0
  7. package/configure/lib/defaults.js +86 -0
  8. package/configure/lib/defaults.js.map +1 -0
  9. package/configure/lib/index.js +99 -0
  10. package/configure/lib/index.js.map +1 -0
  11. package/configure/lib/root.js +135 -0
  12. package/configure/lib/root.js.map +1 -0
  13. package/configure/package.json +23 -0
  14. package/configure/src/__tests__/index.test.js +155 -0
  15. package/configure/src/defaults.js +59 -0
  16. package/configure/src/index.js +114 -0
  17. package/configure/src/root.jsx +116 -0
  18. package/controller/CHANGELOG.json +137 -0
  19. package/controller/CHANGELOG.md +1149 -0
  20. package/controller/lib/defaults.js +14 -0
  21. package/controller/lib/defaults.js.map +1 -0
  22. package/controller/lib/index.js +304 -0
  23. package/controller/lib/index.js.map +1 -0
  24. package/controller/lib/utils.js +70 -0
  25. package/controller/lib/utils.js.map +1 -0
  26. package/controller/package.json +19 -0
  27. package/controller/src/__tests__/index.test.js +711 -0
  28. package/controller/src/defaults.js +7 -0
  29. package/controller/src/index.js +322 -0
  30. package/controller/src/utils.js +72 -0
  31. package/docs/config-schema.json +1382 -0
  32. package/docs/config-schema.json.md +1021 -0
  33. package/docs/demo/config.js +8 -0
  34. package/docs/demo/generate.js +74 -0
  35. package/docs/demo/index.html +1 -0
  36. package/docs/demo/session.js +16 -0
  37. package/docs/pie-schema.json +1085 -0
  38. package/docs/pie-schema.json.md +810 -0
  39. package/lib/constants.js +12 -0
  40. package/lib/constants.js.map +1 -0
  41. package/lib/evaluation-icon.js +60 -0
  42. package/lib/evaluation-icon.js.map +1 -0
  43. package/lib/image-container.js +94 -0
  44. package/lib/image-container.js.map +1 -0
  45. package/lib/image-drop-target.js +130 -0
  46. package/lib/image-drop-target.js.map +1 -0
  47. package/lib/index.js +220 -0
  48. package/lib/index.js.map +1 -0
  49. package/lib/interactive-section.js +104 -0
  50. package/lib/interactive-section.js.map +1 -0
  51. package/lib/possible-response.js +161 -0
  52. package/lib/possible-response.js.map +1 -0
  53. package/lib/possible-responses.js +58 -0
  54. package/lib/possible-responses.js.map +1 -0
  55. package/lib/root.js +491 -0
  56. package/lib/root.js.map +1 -0
  57. package/lib/static-html-span.js +35 -0
  58. package/lib/static-html-span.js.map +1 -0
  59. package/lib/utils-correctness.js +89 -0
  60. package/lib/utils-correctness.js.map +1 -0
  61. package/package.json +21 -86
  62. package/src/__tests__/index.test.js +174 -0
  63. package/src/__tests__/root.test.jsx +99 -0
  64. package/src/__tests__/utils.test.js +207 -0
  65. package/src/constants.js +5 -0
  66. package/src/evaluation-icon.jsx +54 -0
  67. package/src/image-container.jsx +90 -0
  68. package/src/image-drop-target.jsx +140 -0
  69. package/src/index.js +245 -0
  70. package/src/interactive-section.jsx +94 -0
  71. package/src/possible-response.jsx +152 -0
  72. package/src/possible-responses.jsx +52 -0
  73. package/src/root.jsx +490 -0
  74. package/src/static-html-span.jsx +30 -0
  75. package/src/utils-correctness.js +95 -0
  76. package/configure.js +0 -2
  77. package/controller.js +0 -1
  78. package/dist/author/defaults.d.ts +0 -88
  79. package/dist/author/defaults.js +0 -58
  80. package/dist/author/index.d.ts +0 -34
  81. package/dist/author/index.js +0 -71
  82. package/dist/author/root.d.ts +0 -14
  83. package/dist/author/root.js +0 -80
  84. package/dist/browser/Check-DL1c-mLM.js +0 -10708
  85. package/dist/browser/Check-DL1c-mLM.js.map +0 -1
  86. package/dist/browser/author/index.js +0 -38597
  87. package/dist/browser/author/index.js.map +0 -1
  88. package/dist/browser/controller/index.js +0 -171
  89. package/dist/browser/controller/index.js.map +0 -1
  90. package/dist/browser/delivery/index.js +0 -2699
  91. package/dist/browser/delivery/index.js.map +0 -1
  92. package/dist/browser/dist-BphSS14E.js +0 -346
  93. package/dist/browser/dist-BphSS14E.js.map +0 -1
  94. package/dist/browser/humps-CZ4RCLab.js +0 -67
  95. package/dist/browser/humps-CZ4RCLab.js.map +0 -1
  96. package/dist/browser/image-cloze-association.css +0 -2
  97. package/dist/controller/defaults.d.ts +0 -16
  98. package/dist/controller/defaults.js +0 -10
  99. package/dist/controller/index.d.ts +0 -23
  100. package/dist/controller/index.js +0 -122
  101. package/dist/controller/utils.d.ts +0 -14
  102. package/dist/controller/utils.js +0 -36
  103. package/dist/delivery/constants.d.ts +0 -14
  104. package/dist/delivery/evaluation-icon.d.ts +0 -28
  105. package/dist/delivery/evaluation-icon.js +0 -38
  106. package/dist/delivery/image-container.d.ts +0 -13
  107. package/dist/delivery/image-container.js +0 -61
  108. package/dist/delivery/image-drop-target.d.ts +0 -45
  109. package/dist/delivery/image-drop-target.js +0 -90
  110. package/dist/delivery/index.d.ts +0 -20
  111. package/dist/delivery/index.js +0 -110
  112. package/dist/delivery/interactive-section.d.ts +0 -15
  113. package/dist/delivery/interactive-section.js +0 -72
  114. package/dist/delivery/possible-response.d.ts +0 -34
  115. package/dist/delivery/possible-response.js +0 -100
  116. package/dist/delivery/possible-responses.d.ts +0 -31
  117. package/dist/delivery/possible-responses.js +0 -41
  118. package/dist/delivery/root.d.ts +0 -21
  119. package/dist/delivery/root.js +0 -278
  120. package/dist/delivery/static-html-span.d.ts +0 -14
  121. package/dist/delivery/static-html-span.js +0 -22
  122. package/dist/delivery/utils-correctness.d.ts +0 -10
  123. package/dist/delivery/utils-correctness.js +0 -43
  124. package/dist/index.d.ts +0 -1
  125. package/dist/index.iife.d.ts +0 -8
  126. package/dist/index.iife.js +0 -152
  127. package/dist/index.js +0 -2
  128. package/dist/node_modules/.bun/clsx@2.1.1/node_modules/clsx/dist/clsx.js +0 -16
  129. package/dist/runtime-support.d.ts +0 -12
  130. package/dist/runtime-support.js +0 -12
@@ -0,0 +1,207 @@
1
+ import { getAnswersCorrectness } from '../utils-correctness';
2
+
3
+ const rhomb = 'rhomb';
4
+ const trapeze = 'trapeze';
5
+ const hexagon = 'hexagon';
6
+
7
+ const answer1 = {
8
+ containerIndex: 0,
9
+ id: 1,
10
+ value: rhomb,
11
+ };
12
+ const answer2 = {
13
+ containerIndex: 0,
14
+ id: 2,
15
+ value: rhomb,
16
+ };
17
+ const answer3 = {
18
+ containerIndex: 0,
19
+ id: 3,
20
+ value: trapeze,
21
+ };
22
+
23
+ const answer4 = {
24
+ containerIndex: 1,
25
+ id: 4,
26
+ value: hexagon,
27
+ };
28
+
29
+ describe('utils', () => {
30
+ let validResponses;
31
+
32
+ beforeEach(() => {
33
+ validResponses = {
34
+ validResponse: {
35
+ value: [{ images: [rhomb] }, { images: [rhomb, trapeze] }],
36
+ },
37
+ };
38
+ });
39
+
40
+ describe('correctness', () => {
41
+ it('marks correct answers as correct', () => {
42
+ const result = getAnswersCorrectness(
43
+ [
44
+ answer1,
45
+ {
46
+ ...answer3,
47
+ containerIndex: 1,
48
+ },
49
+ ],
50
+ validResponses,
51
+ );
52
+ expect(result).toEqual([
53
+ {
54
+ ...answer1,
55
+ isCorrect: true,
56
+ },
57
+ {
58
+ ...answer3,
59
+ isCorrect: true,
60
+ containerIndex: 1,
61
+ },
62
+ ]);
63
+ });
64
+
65
+ it('marks incorrect answers as incorrect', () => {
66
+ const result = getAnswersCorrectness([answer1, answer3], validResponses);
67
+ expect(result).toEqual([
68
+ {
69
+ ...answer1,
70
+ isCorrect: true,
71
+ },
72
+ {
73
+ ...answer3,
74
+ isCorrect: false,
75
+ },
76
+ ]);
77
+ });
78
+
79
+ it('marks duplicates as incorrect', () => {
80
+ const result = getAnswersCorrectness([answer1, answer2], validResponses);
81
+ expect(result).toEqual([
82
+ {
83
+ ...answer1,
84
+ isCorrect: true,
85
+ },
86
+ {
87
+ ...answer2,
88
+ isCorrect: false,
89
+ },
90
+ ]);
91
+ });
92
+
93
+ it('marks duplicates and incorrect as incorrect', () => {
94
+ const result = getAnswersCorrectness([answer1, answer2, answer3], validResponses);
95
+ expect(result).toEqual([
96
+ {
97
+ ...answer1,
98
+ isCorrect: true,
99
+ },
100
+ {
101
+ ...answer2,
102
+ isCorrect: false,
103
+ },
104
+ {
105
+ ...answer3,
106
+ isCorrect: false,
107
+ },
108
+ ]);
109
+ });
110
+
111
+ describe('alternate correct answers', () => {
112
+ describe('handles one option', () => {
113
+ it('marks correct answers as correct', () => {
114
+ const result = getAnswersCorrectness([answer1, answer4], {
115
+ ...validResponses,
116
+ altResponses: [
117
+ {
118
+ value: [{ images: [rhomb] }, { images: [hexagon] }],
119
+ },
120
+ ],
121
+ });
122
+ expect(result).toEqual([
123
+ {
124
+ ...answer1,
125
+ isCorrect: true,
126
+ },
127
+ {
128
+ ...answer4,
129
+ isCorrect: true,
130
+ },
131
+ ]);
132
+ });
133
+
134
+ it('marks incorrect answers as incorrect', () => {
135
+ const result = getAnswersCorrectness([answer1, answer4], {
136
+ ...validResponses,
137
+ altResponses: [
138
+ {
139
+ value: [{ images: [hexagon] }, { images: [rhomb] }],
140
+ },
141
+ ],
142
+ });
143
+ expect(result).toEqual([
144
+ {
145
+ ...answer1,
146
+ isCorrect: false,
147
+ },
148
+ {
149
+ ...answer4,
150
+ isCorrect: false,
151
+ },
152
+ ]);
153
+ });
154
+ });
155
+
156
+ describe('handles multiple options', () => {
157
+ it('marks correct answers as correct', () => {
158
+ const result = getAnswersCorrectness([answer1, answer4], {
159
+ ...validResponses,
160
+ altResponses: [
161
+ {
162
+ value: [{ images: [hexagon] }, { images: [rhomb] }],
163
+ },
164
+ {
165
+ value: [{ images: [rhomb] }, { images: [hexagon] }],
166
+ },
167
+ ],
168
+ });
169
+ expect(result).toEqual([
170
+ {
171
+ ...answer1,
172
+ isCorrect: true,
173
+ },
174
+ {
175
+ ...answer4,
176
+ isCorrect: true,
177
+ },
178
+ ]);
179
+ });
180
+
181
+ it('marks incorrect answers as incorrect', () => {
182
+ const result = getAnswersCorrectness([answer1, answer4], {
183
+ ...validResponses,
184
+ altResponses: [
185
+ {
186
+ value: [{ images: [hexagon] }, { images: [rhomb] }],
187
+ },
188
+ {
189
+ value: [{ images: [hexagon] }, { images: [hexagon] }],
190
+ },
191
+ ],
192
+ });
193
+ expect(result).toEqual([
194
+ {
195
+ ...answer1,
196
+ isCorrect: false,
197
+ },
198
+ {
199
+ ...answer4,
200
+ isCorrect: true,
201
+ },
202
+ ]);
203
+ });
204
+ });
205
+ });
206
+ });
207
+ });
@@ -0,0 +1,5 @@
1
+ export default {
2
+ types: {
3
+ response: 'react-dnd-response',
4
+ },
5
+ };
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { styled } from '@mui/material/styles';
4
+ import Check from '@mui/icons-material/Check';
5
+ import Close from '@mui/icons-material/Close';
6
+ import { color } from '@pie-lib/render-ui';
7
+
8
+ const StyledIcon = styled('svg')(() => ({
9
+ '&.correctEmpty': {
10
+ color: color.correct(),
11
+ },
12
+ '&.correctFilled': {
13
+ color: color.background(),
14
+ backgroundColor: color.correct(),
15
+ },
16
+ '&.incorrectEmpty': {
17
+ color: color.incorrect(),
18
+ },
19
+ '&.incorrectFilled': {
20
+ color: color.background(),
21
+ backgroundColor: color.incorrect(),
22
+ },
23
+ }));
24
+
25
+ const getCorrectnessClass = (isCorrect, filled) => {
26
+ const correctness = isCorrect ? 'correct' : 'incorrect';
27
+ const fillState = filled ? 'Filled' : 'Empty';
28
+
29
+ return `${correctness}${fillState}`;
30
+ };
31
+
32
+ const EvaluationIcon = ({ containerStyle, isCorrect, filled }) => {
33
+ const Icon = isCorrect ? Check : Close;
34
+ const showCorrectness = isCorrect !== undefined;
35
+ const correctness = showCorrectness ? getCorrectnessClass(isCorrect, filled) : '';
36
+
37
+ return showCorrectness ? (
38
+ <Icon component={StyledIcon} className={correctness} style={containerStyle} />
39
+ ) : null;
40
+ };
41
+
42
+ EvaluationIcon.propTypes = {
43
+ containerStyle: PropTypes.object,
44
+ filled: PropTypes.bool,
45
+ isCorrect: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
46
+ };
47
+
48
+ EvaluationIcon.defaultProps = {
49
+ containerStyle: {},
50
+ filled: false,
51
+ isCorrect: undefined,
52
+ };
53
+
54
+ export default EvaluationIcon;
@@ -0,0 +1,90 @@
1
+ import React, { Component } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { styled } from '@mui/material/styles';
4
+
5
+ import ImageDropTarget from './image-drop-target';
6
+
7
+ const BaseContainer = styled('div')(({ theme }) => ({
8
+ margin: theme.spacing(2),
9
+ position: 'relative',
10
+ width: 'fit-content',
11
+ }));
12
+
13
+ class ImageContainer extends Component {
14
+ render() {
15
+ const {
16
+ answers,
17
+ canDrag,
18
+ draggingElement,
19
+ image: { height, src, width } = {},
20
+ onAnswerSelect,
21
+ onDragAnswerBegin,
22
+ onDragAnswerEnd,
23
+ responseContainers,
24
+ showDashedBorder,
25
+ responseAreaFill,
26
+ answerChoiceTransparency,
27
+ responseContainerPadding,
28
+ imageDropTargetPadding,
29
+ maxResponsePerZone,
30
+ } = this.props;
31
+
32
+ return (
33
+ <BaseContainer>
34
+ <img src={src} height={height} width={width} />
35
+
36
+ {(responseContainers || []).map((r, i) => {
37
+ const rHeight = (r.height.replace('%', '') / 100) * height;
38
+ const rWidth = (r.width.replace('%', '') / 100) * width;
39
+ const rLeft = (r.x / 100) * width;
40
+ const rTop = (r.y / 100) * height;
41
+ const answersParsed = answers.filter((a) => a.containerIndex === r.index);
42
+
43
+ return (
44
+ <ImageDropTarget
45
+ answers={answersParsed}
46
+ canDrag={canDrag}
47
+ containerStyle={{
48
+ height: rHeight,
49
+ width: rWidth,
50
+ left: rLeft,
51
+ top: rTop,
52
+ }}
53
+ key={r.id + i}
54
+ draggingElement={draggingElement}
55
+ index={r.index}
56
+ onDrop={(item) => onAnswerSelect(item, r.index)}
57
+ onDragAnswerBegin={onDragAnswerBegin}
58
+ onDragAnswerEnd={onDragAnswerEnd}
59
+ showDashedBorder={showDashedBorder}
60
+ responseAreaFill={responseAreaFill}
61
+ answerChoiceTransparency={answerChoiceTransparency}
62
+ responseContainerPadding={responseContainerPadding}
63
+ imageDropTargetPadding={imageDropTargetPadding}
64
+ maxResponsePerZone={maxResponsePerZone}
65
+ />
66
+ );
67
+ })}
68
+ </BaseContainer>
69
+ );
70
+ }
71
+ }
72
+
73
+ ImageContainer.propTypes = {
74
+ answers: PropTypes.array.isRequired,
75
+ canDrag: PropTypes.bool.isRequired,
76
+ draggingElement: PropTypes.shape({}).isRequired,
77
+ image: PropTypes.object.isRequired,
78
+ onAnswerSelect: PropTypes.func.isRequired,
79
+ onDragAnswerBegin: PropTypes.func.isRequired,
80
+ onDragAnswerEnd: PropTypes.func.isRequired,
81
+ responseContainers: PropTypes.array.isRequired,
82
+ showDashedBorder: PropTypes.bool,
83
+ answerChoiceTransparency: PropTypes.bool,
84
+ responseAreaFill: PropTypes.string,
85
+ responseContainerPadding: PropTypes.string,
86
+ imageDropTargetPadding: PropTypes.string,
87
+ maxResponsePerZone: PropTypes.number,
88
+ };
89
+
90
+ export default ImageContainer;
@@ -0,0 +1,140 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useDroppable } from '@dnd-kit/core';
4
+ import { styled } from '@mui/material/styles';
5
+ import { color } from '@pie-lib/render-ui';
6
+ import cx from 'classnames';
7
+
8
+ import PossibleResponse from './possible-response';
9
+
10
+ const AnswersContainer = styled('div')(() => ({
11
+ display: 'flex',
12
+ flexWrap: 'wrap',
13
+ }));
14
+
15
+ const ResponseContainer = styled('div')(() => ({
16
+ position: 'absolute',
17
+ boxSizing: 'border-box',
18
+ '&.active': {
19
+ border: `2px solid ${color.text()}`,
20
+ backgroundColor: 'rgba(230, 242, 252, .8)',
21
+ },
22
+ '&.dashed': {
23
+ border: `2px dashed ${color.text()}`,
24
+ },
25
+ '&.is-over': {
26
+ border: '1px solid rgb(158, 158, 158)',
27
+ backgroundColor: 'rgb(224, 224, 224)',
28
+ },
29
+ }));
30
+
31
+ const ImageDropTarget = ({
32
+ answers,
33
+ canDrag,
34
+ containerStyle,
35
+ draggingElement,
36
+ onDragAnswerBegin,
37
+ onDragAnswerEnd,
38
+ showDashedBorder,
39
+ responseAreaFill,
40
+ responseContainerPadding = '10px',
41
+ imageDropTargetPadding,
42
+ answerChoiceTransparency,
43
+ maxResponsePerZone,
44
+ onDrop,
45
+ index,
46
+ }) => {
47
+ const [shouldHaveSmallPadding, setShouldHaveSmallPadding] = useState(false);
48
+ const dropContainerRef = useRef(null);
49
+ const dropContainerResponsesHeightRef = useRef(null);
50
+
51
+ const { setNodeRef, isOver } = useDroppable({
52
+ id: `response-container-${index}`,
53
+ data: {
54
+ containerIndex: index,
55
+ onDrop,
56
+ },
57
+ });
58
+
59
+ useEffect(() => {
60
+ const container = dropContainerRef.current;
61
+
62
+ if (!container) return;
63
+
64
+ const handleTouchStart = (e) => {
65
+ e.preventDefault();
66
+ };
67
+
68
+ container.addEventListener('touchstart', handleTouchStart, { passive: false });
69
+
70
+ return () => {
71
+ container.removeEventListener('touchstart', handleTouchStart);
72
+ };
73
+ }, []);
74
+
75
+ const isDraggingElement = !!draggingElement.id;
76
+
77
+ const containerClasses = cx({
78
+ 'is-over': isOver,
79
+ dashed: showDashedBorder && !isDraggingElement,
80
+ active: isDraggingElement,
81
+ });
82
+
83
+ const updatedContainerStyle = {
84
+ padding: maxResponsePerZone === 1 ? '0' : responseContainerPadding,
85
+ ...containerStyle,
86
+ ...(responseAreaFill && !isDraggingElement && { backgroundColor: responseAreaFill }),
87
+ };
88
+
89
+ return (
90
+ <ResponseContainer
91
+ ref={(ref) => {
92
+ dropContainerRef.current = ref;
93
+ setNodeRef(ref);
94
+ }}
95
+ className={containerClasses}
96
+ style={updatedContainerStyle}
97
+ >
98
+ {answers.length ? (
99
+ <AnswersContainer
100
+ ref={(ref) => {
101
+ dropContainerResponsesHeightRef.current = ref?.getBoundingClientRect().height;
102
+ }}
103
+ >
104
+ {answers.map((answer) => (
105
+ <PossibleResponse
106
+ key={answer.id}
107
+ data={answer}
108
+ canDrag={canDrag}
109
+ onDragBegin={() => onDragAnswerBegin(answer)}
110
+ onDragEnd={onDragAnswerEnd}
111
+ answerChoiceTransparency={answerChoiceTransparency}
112
+ containerStyle={{
113
+ padding: imageDropTargetPadding ? imageDropTargetPadding : shouldHaveSmallPadding ? '2px' : '6px 10px',
114
+ }}
115
+ />
116
+ ))}
117
+ </AnswersContainer>
118
+ ) : null}
119
+ </ResponseContainer>
120
+ );
121
+ };
122
+
123
+ ImageDropTarget.propTypes = {
124
+ answer: PropTypes.object,
125
+ answers: PropTypes.array,
126
+ canDrag: PropTypes.bool.isRequired,
127
+ containerStyle: PropTypes.object.isRequired,
128
+ draggingElement: PropTypes.object.isRequired,
129
+ onDragAnswerBegin: PropTypes.func.isRequired,
130
+ onDragAnswerEnd: PropTypes.func.isRequired,
131
+ onDrop: PropTypes.func.isRequired,
132
+ showDashedBorder: PropTypes.bool,
133
+ responseAreaFill: PropTypes.string,
134
+ answerChoiceTransparency: PropTypes.bool,
135
+ responseContainerPadding: PropTypes.string,
136
+ imageDropTargetPadding: PropTypes.string,
137
+ maxResponsePerZone: PropTypes.number,
138
+ };
139
+
140
+ export default ImageDropTarget;