catchup-library-web 2.5.8 → 2.5.10
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.
- package/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +158 -218
- package/dist/index.mjs +177 -237
- package/package.json +1 -1
- package/src/components/activities/MatchingActivityContent.tsx +28 -17
- package/src/components/activities/OrderingActivityContent.tsx +28 -17
- package/src/components/activities/body-contents/ActivityBodyContent.tsx +1 -1
- package/src/components/activities/body-contents/ShowBodyMediaByContentType.tsx +2 -6
- package/src/components/activities/material-contents/FillInTheBlanksActivityMaterialContent.tsx +19 -19
- package/src/components/activities/material-contents/GroupingActivityMaterialContent.tsx +24 -24
- package/src/components/activities/material-contents/MatchingActivityMaterialContent.tsx +25 -25
- package/src/components/activities/material-contents/OrderingActivityMaterialContent.tsx +16 -55
- package/src/components/activities/material-contents/ShowMaterialMediaByContentType.tsx +1 -1
- package/src/components/groups/InputGroup.tsx +2 -2
- package/src/components/groups/PageTravelGroup.tsx +46 -86
- package/src/properties/ActivityProperties.ts +2 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { useEffect, useState, useRef } from "react";
|
|
2
2
|
import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
|
|
3
3
|
import { InlineMath } from "react-katex";
|
|
4
|
-
import useScreenSize from "../../../hooks/useScreenSize";
|
|
5
4
|
import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
|
|
6
5
|
import { IOrderingActivityMaterialProps } from "../../../properties/ActivityProperties";
|
|
7
6
|
|
|
@@ -19,7 +18,7 @@ const OrderingActivityMaterialContent = ({
|
|
|
19
18
|
const [draggedKey, setDraggedKey] = useState<string | null>(null);
|
|
20
19
|
const [dropTargetKey, setDropTargetKey] = useState<string | null>(null);
|
|
21
20
|
const [draggedElement, setDraggedElement] = useState<HTMLElement | null>(
|
|
22
|
-
null
|
|
21
|
+
null,
|
|
23
22
|
);
|
|
24
23
|
const dragElementRef = useRef<HTMLDivElement>(null);
|
|
25
24
|
const [mousePosition, setMousePosition] = useState<{ x: number; y: number }>({
|
|
@@ -30,19 +29,8 @@ const OrderingActivityMaterialContent = ({
|
|
|
30
29
|
x: 0,
|
|
31
30
|
y: 0,
|
|
32
31
|
});
|
|
33
|
-
const { screenSize } = useScreenSize();
|
|
34
|
-
const [view, setView] = useState("PC");
|
|
35
32
|
const [displayAnswerMap, setDisplayAnswerMap] = useState<any>(answerMap);
|
|
36
33
|
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
if (!screenSize) return;
|
|
39
|
-
if (screenSize.width <= 1024) {
|
|
40
|
-
setView("TABLET");
|
|
41
|
-
} else {
|
|
42
|
-
setView("PC");
|
|
43
|
-
}
|
|
44
|
-
}, [screenSize]);
|
|
45
|
-
|
|
46
34
|
useEffect(() => {
|
|
47
35
|
if (showCorrectAnswer) {
|
|
48
36
|
const correctAnswerMap: any = {};
|
|
@@ -63,27 +51,6 @@ const OrderingActivityMaterialContent = ({
|
|
|
63
51
|
return "INCORRECT";
|
|
64
52
|
};
|
|
65
53
|
|
|
66
|
-
const calculateMarginTop = (index: number) => {
|
|
67
|
-
if (index === 0) {
|
|
68
|
-
return 0;
|
|
69
|
-
} else if (index === 1) {
|
|
70
|
-
if (contentMap.type === "TEXT") {
|
|
71
|
-
return 65;
|
|
72
|
-
} else {
|
|
73
|
-
return 130;
|
|
74
|
-
}
|
|
75
|
-
} else if (index % 2 === 0) {
|
|
76
|
-
if (contentMap.type === "TEXT") {
|
|
77
|
-
return -65;
|
|
78
|
-
} else {
|
|
79
|
-
return -130;
|
|
80
|
-
}
|
|
81
|
-
} else if (index % 2 === 1) {
|
|
82
|
-
return 0;
|
|
83
|
-
}
|
|
84
|
-
return 0;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
54
|
const handleMouseDown = (e: React.MouseEvent, materialKey: string): void => {
|
|
88
55
|
if (!checkCanAnswerQuestion()) return;
|
|
89
56
|
e.preventDefault();
|
|
@@ -125,7 +92,7 @@ const OrderingActivityMaterialContent = ({
|
|
|
125
92
|
const handleTouchStart = (
|
|
126
93
|
e: React.TouchEvent,
|
|
127
94
|
materialKey: string,
|
|
128
|
-
element: HTMLElement
|
|
95
|
+
element: HTMLElement,
|
|
129
96
|
): void => {
|
|
130
97
|
if (!checkCanAnswerQuestion()) return;
|
|
131
98
|
const touch = e.touches[0];
|
|
@@ -144,7 +111,7 @@ const OrderingActivityMaterialContent = ({
|
|
|
144
111
|
// Find the element under the touch point
|
|
145
112
|
const elementUnder = document.elementFromPoint(
|
|
146
113
|
touch.clientX,
|
|
147
|
-
touch.clientY
|
|
114
|
+
touch.clientY,
|
|
148
115
|
);
|
|
149
116
|
const dropZone = elementUnder?.closest("[data-ordering-drop-zone]");
|
|
150
117
|
|
|
@@ -200,10 +167,10 @@ const OrderingActivityMaterialContent = ({
|
|
|
200
167
|
}}
|
|
201
168
|
>
|
|
202
169
|
{contentMap.type === "TEXT" ? (
|
|
203
|
-
<div className="border-catchup-blue border-2 px-3 py-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
170
|
+
<div className="border-catchup-blue border-2 px-3 py-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
204
171
|
<p className="text-xl whitespace-pre-wrap">
|
|
205
172
|
{constructInputWithSpecialExpressionList(
|
|
206
|
-
materialMap[displayAnswerMap[draggedKey]]
|
|
173
|
+
materialMap[displayAnswerMap[draggedKey]],
|
|
207
174
|
).map((inputPart, index) => (
|
|
208
175
|
<span
|
|
209
176
|
key={index}
|
|
@@ -223,7 +190,7 @@ const OrderingActivityMaterialContent = ({
|
|
|
223
190
|
</p>
|
|
224
191
|
</div>
|
|
225
192
|
) : (
|
|
226
|
-
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-white shadow-lg">
|
|
193
|
+
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
227
194
|
<ShowMaterialMediaByContentType
|
|
228
195
|
key={`${uniqueValue}-drag-mouse`}
|
|
229
196
|
contentType={contentMap.type}
|
|
@@ -245,10 +212,10 @@ const OrderingActivityMaterialContent = ({
|
|
|
245
212
|
}}
|
|
246
213
|
>
|
|
247
214
|
{contentMap.type === "TEXT" ? (
|
|
248
|
-
<div className="border-catchup-blue border-2 px-3 py-2 rounded-catchup-xlarge bg-white shadow-lg">
|
|
215
|
+
<div className="border-catchup-blue border-2 px-3 py-2 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
249
216
|
<p className="text-xl whitespace-pre-wrap">
|
|
250
217
|
{constructInputWithSpecialExpressionList(
|
|
251
|
-
materialMap[displayAnswerMap[draggedKey]]
|
|
218
|
+
materialMap[displayAnswerMap[draggedKey]],
|
|
252
219
|
).map((inputPart, index) => (
|
|
253
220
|
<span
|
|
254
221
|
key={index}
|
|
@@ -268,7 +235,7 @@ const OrderingActivityMaterialContent = ({
|
|
|
268
235
|
</p>
|
|
269
236
|
</div>
|
|
270
237
|
) : (
|
|
271
|
-
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-white shadow-lg">
|
|
238
|
+
<div className="border-catchup-blue border-2 px-2 py-1 rounded-catchup-xlarge bg-catchup-white shadow-lg">
|
|
272
239
|
<ShowMaterialMediaByContentType
|
|
273
240
|
key={`${uniqueValue}-drag-touch`}
|
|
274
241
|
contentType={contentMap.type}
|
|
@@ -283,18 +250,12 @@ const OrderingActivityMaterialContent = ({
|
|
|
283
250
|
{Object.keys(displayAnswerMap).map((materialKey, index) => {
|
|
284
251
|
const learnerAnswerState = checkAnswerState(
|
|
285
252
|
displayAnswerMap[materialKey] + "",
|
|
286
|
-
index + ""
|
|
253
|
+
index + "",
|
|
287
254
|
);
|
|
288
255
|
return (
|
|
289
|
-
<div className="w-full
|
|
256
|
+
<div className="w-full" key={index}>
|
|
290
257
|
<div
|
|
291
258
|
className={`flex flex-row items-center my-4 mx-2`}
|
|
292
|
-
style={{
|
|
293
|
-
marginTop:
|
|
294
|
-
view === "PC"
|
|
295
|
-
? calculateMarginTop(parseFloat(materialKey))
|
|
296
|
-
: 0,
|
|
297
|
-
}}
|
|
298
259
|
>
|
|
299
260
|
<div className="mr-3">
|
|
300
261
|
<div className="h-catchup-activity-box-item w-catchup-activity-box-item flex flex-col items-center justify-center cursor-pointer transition-all duration-300 overflow-y-auto">
|
|
@@ -317,8 +278,8 @@ const OrderingActivityMaterialContent = ({
|
|
|
317
278
|
draggedKey === materialKey
|
|
318
279
|
? "opacity-40"
|
|
319
280
|
: selectedKey === materialKey
|
|
320
|
-
|
|
321
|
-
|
|
281
|
+
? "ring-2 ring-blue-500"
|
|
282
|
+
: "opacity-100"
|
|
322
283
|
} ${
|
|
323
284
|
dropTargetKey === materialKey && draggedKey !== materialKey
|
|
324
285
|
? "ring-2 ring-blue-400 bg-blue-50"
|
|
@@ -346,15 +307,15 @@ const OrderingActivityMaterialContent = ({
|
|
|
346
307
|
learnerAnswerState === "CORRECT"
|
|
347
308
|
? "border-catchup-green"
|
|
348
309
|
: learnerAnswerState === "INCORRECT"
|
|
349
|
-
|
|
350
|
-
|
|
310
|
+
? "border-catchup-red"
|
|
311
|
+
: "border-catchup-blue"
|
|
351
312
|
}`}
|
|
352
313
|
onClick={() => handleSelectItem(materialKey)}
|
|
353
314
|
>
|
|
354
315
|
{contentMap.type === "TEXT" ? (
|
|
355
316
|
<p className="text-xl whitespace-pre-wrap">
|
|
356
317
|
{constructInputWithSpecialExpressionList(
|
|
357
|
-
materialMap[displayAnswerMap[materialKey]]
|
|
318
|
+
materialMap[displayAnswerMap[materialKey]],
|
|
358
319
|
).map((inputPart, index) => (
|
|
359
320
|
<span
|
|
360
321
|
key={index}
|
|
@@ -100,7 +100,7 @@ const ShowMaterialMediaByContentType = ({
|
|
|
100
100
|
src !== "DEFAULT_OPTION" &&
|
|
101
101
|
canFullScreen ? (
|
|
102
102
|
<div
|
|
103
|
-
className="absolute flex items-center justify-center top-2 right-2 h-6 w-6 cursor-pointer border rounded-catchup-xlarge border-catchup-blue p-1 bg-white bg-opacity-80"
|
|
103
|
+
className="absolute flex items-center justify-center top-2 right-2 h-6 w-6 cursor-pointer border rounded-catchup-xlarge border-catchup-blue p-1 bg-catchup-white bg-opacity-80"
|
|
104
104
|
onMouseEnter={(e) => {
|
|
105
105
|
e.preventDefault();
|
|
106
106
|
}}
|
|
@@ -178,7 +178,7 @@ const InputGroup = ({
|
|
|
178
178
|
setShowMathConstructor(false);
|
|
179
179
|
}}
|
|
180
180
|
>
|
|
181
|
-
<div className="bg-white rounded-lg overflow-hidden">
|
|
181
|
+
<div className="bg-catchup-white rounded-lg overflow-hidden">
|
|
182
182
|
<div className="p-6 space-y-6">
|
|
183
183
|
<div>
|
|
184
184
|
<div className="border border-catchup-gray-100 rounded-catchup-large focus-within:border-catchup-blue-400 focus-within:shadow-input">
|
|
@@ -482,7 +482,7 @@ const InputGroup = ({
|
|
|
482
482
|
? "border-catchup-red shadow-error"
|
|
483
483
|
: "border-catchup-gray-100"
|
|
484
484
|
} rounded-catchup-large focus-within:border-catchup-blue-400 focus-within:shadow-input ${
|
|
485
|
-
disabled ? "bg-catchup-lighter-gray" : "bg-white"
|
|
485
|
+
disabled ? "bg-catchup-lighter-gray" : "bg-catchup-white"
|
|
486
486
|
}`}
|
|
487
487
|
>
|
|
488
488
|
<input
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import { IPageTravelGroupProps } from "../../properties/GroupProperties";
|
|
3
|
-
import BaseImage from "../images/BaseImage";
|
|
4
3
|
|
|
5
4
|
const PageTravelGroup = ({
|
|
6
5
|
isImageProcessing,
|
|
@@ -22,92 +21,53 @@ const PageTravelGroup = ({
|
|
|
22
21
|
setNewPageNumber(pageNumber + 1);
|
|
23
22
|
}, [pageNumber]);
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
onClick={() => {
|
|
34
|
-
if (isImageProcessing) {
|
|
35
|
-
handleImageProcessing();
|
|
36
|
-
} else {
|
|
37
|
-
if (pageNumber - 1 >= 0) {
|
|
38
|
-
setPageNumber(pageNumber - 1);
|
|
39
|
-
}
|
|
40
|
-
setImageReady(false);
|
|
41
|
-
}
|
|
42
|
-
}}
|
|
43
|
-
/>
|
|
44
|
-
</div>
|
|
45
|
-
)}
|
|
46
|
-
{Array.from(Array(totalPageNumber).keys())
|
|
47
|
-
.filter((index) => index < pageNumber + 5)
|
|
48
|
-
.filter((index) => index > pageNumber - 5)
|
|
49
|
-
.map((index) => (
|
|
50
|
-
<div key={index} className="px-2">
|
|
51
|
-
<p
|
|
52
|
-
className={`${
|
|
53
|
-
pageNumber === index ? "text-xl" : "text-md"
|
|
54
|
-
} cursor-pointer`}
|
|
55
|
-
onClick={() => {
|
|
56
|
-
if (isImageProcessing) {
|
|
57
|
-
handleImageProcessing();
|
|
58
|
-
} else {
|
|
59
|
-
setPageNumber(index);
|
|
60
|
-
setImageReady(false);
|
|
61
|
-
}
|
|
62
|
-
}}
|
|
63
|
-
>
|
|
64
|
-
{index + 1}
|
|
65
|
-
</p>
|
|
66
|
-
</div>
|
|
67
|
-
))}
|
|
68
|
-
|
|
69
|
-
{totalPageNumber === 0 || pageNumber === totalPageNumber - 1 ? null : (
|
|
70
|
-
<div className="px-2 flex flex-col items-center">
|
|
71
|
-
<BaseImage
|
|
72
|
-
size="small"
|
|
73
|
-
alt="arrow-right"
|
|
74
|
-
src="/icons/arrow-right.webp"
|
|
75
|
-
onClick={() => {
|
|
76
|
-
if (isImageProcessing) {
|
|
77
|
-
handleImageProcessing();
|
|
78
|
-
} else {
|
|
79
|
-
if (pageNumber + 1 <= totalPageNumber) {
|
|
80
|
-
setPageNumber(pageNumber + 1);
|
|
81
|
-
}
|
|
24
|
+
const handlePageChange = (newPage: number) => {
|
|
25
|
+
if (isImageProcessing) {
|
|
26
|
+
handleImageProcessing();
|
|
27
|
+
} else {
|
|
28
|
+
setPageNumber(newPage);
|
|
29
|
+
setImageReady(false);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
82
32
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
33
|
+
return (
|
|
34
|
+
<div className="flex-1 flex flex-row justify-center items-center flex-wrap gap-x-2">
|
|
35
|
+
<button
|
|
36
|
+
className="px-2 py-1 bg-catchup-blue-100 rounded-catchup-small"
|
|
37
|
+
disabled={pageNumber <= 0}
|
|
38
|
+
onClick={() => handlePageChange(pageNumber - 1)}
|
|
39
|
+
>
|
|
40
|
+
←
|
|
41
|
+
</button>
|
|
42
|
+
<p className="text-md">
|
|
43
|
+
{pageNumber + 1} / {totalPageNumber}
|
|
44
|
+
</p>
|
|
45
|
+
<button
|
|
46
|
+
className="px-2 py-1 bg-catchup-blue-100 rounded-catchup-small"
|
|
47
|
+
disabled={pageNumber >= totalPageNumber - 1}
|
|
48
|
+
onClick={() => handlePageChange(pageNumber + 1)}
|
|
49
|
+
>
|
|
50
|
+
→
|
|
51
|
+
</button>
|
|
52
|
+
<input
|
|
53
|
+
className="w-[90px] py-2 px-4 border border-catchup-gray-100 rounded-catchup-xlarge focus:outline-none placeholder-catchup-gray-200 focus:border-catchup-blue-400 focus:shadow-input"
|
|
54
|
+
type="number"
|
|
55
|
+
value={newPageNumber}
|
|
56
|
+
onChange={(e) => {
|
|
57
|
+
setNewPageNumber(parseInt(e.target.value));
|
|
58
|
+
}}
|
|
59
|
+
onKeyDown={(e) => {
|
|
60
|
+
if (
|
|
61
|
+
isNaN(newPageNumber) ||
|
|
62
|
+
newPageNumber <= 0 ||
|
|
63
|
+
newPageNumber > totalPageNumber
|
|
64
|
+
)
|
|
65
|
+
return;
|
|
66
|
+
if (e.key === "Enter") {
|
|
67
|
+
handlePageChange(newPageNumber - 1);
|
|
68
|
+
}
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
111
71
|
</div>
|
|
112
72
|
);
|
|
113
73
|
};
|
|
@@ -26,6 +26,7 @@ export interface IOrderingActivityProps {
|
|
|
26
26
|
changeAnswer: (e: any) => void;
|
|
27
27
|
isPreview: boolean;
|
|
28
28
|
showCorrectAnswer: boolean;
|
|
29
|
+
isFullScreen: boolean;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export interface IOrderingActivityMaterialProps {
|
|
@@ -129,6 +130,7 @@ export interface IMatchingActivityProps {
|
|
|
129
130
|
changeAnswer: (e: any) => void;
|
|
130
131
|
isPreview: boolean;
|
|
131
132
|
showCorrectAnswer: boolean;
|
|
133
|
+
isFullScreen: boolean;
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
export interface IMatchingActivityMaterialProps {
|