catchup-library-web 1.21.1 → 1.21.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.
package/dist/index.js CHANGED
@@ -5747,16 +5747,22 @@ var MatchingActivityMaterialContent = ({
5747
5747
  const [selectedValue, setSelectedValue] = (0, import_react21.useState)(null);
5748
5748
  const [draggedValue, setDraggedValue] = (0, import_react21.useState)(null);
5749
5749
  const [dropTargetKey, setDropTargetKey] = (0, import_react21.useState)(null);
5750
- const [draggedElement, setDraggedElement] = (0, import_react21.useState)(null);
5750
+ const [draggedElement, setDraggedElement] = (0, import_react21.useState)(
5751
+ null
5752
+ );
5751
5753
  const [isShuffled, setIsShuffled] = (0, import_react21.useState)(false);
5752
5754
  const [shuffledMaterialList, setShuffledMaterialList] = (0, import_react21.useState)([]);
5753
5755
  const dragElementRef = (0, import_react21.useRef)(null);
5754
- const [mousePosition, setMousePosition] = (0, import_react21.useState)({ x: 0, y: 0 });
5755
- const [touchPosition, setTouchPosition] = (0, import_react21.useState)({ x: 0, y: 0 });
5756
+ const [mousePosition, setMousePosition] = (0, import_react21.useState)({
5757
+ x: 0,
5758
+ y: 0
5759
+ });
5760
+ const [touchPosition, setTouchPosition] = (0, import_react21.useState)({
5761
+ x: 0,
5762
+ y: 0
5763
+ });
5756
5764
  const itemsRef = (0, import_react21.useRef)(null);
5757
- const scrollIntervalRef = (0, import_react21.useRef)(null);
5758
- const SCROLL_THRESHOLD = 100;
5759
- const SCROLL_SPEED = 10;
5765
+ const dropZoneRefs = (0, import_react21.useRef)({});
5760
5766
  (0, import_react21.useEffect)(() => {
5761
5767
  const shuffleArray2 = (array) => {
5762
5768
  if (!isShuffled) {
@@ -5778,44 +5784,21 @@ var MatchingActivityMaterialContent = ({
5778
5784
  }, [materialMap, isShuffled]);
5779
5785
  (0, import_react21.useEffect)(() => {
5780
5786
  if (!showCorrectAnswer) return;
5781
- answer.data.find((answerData) => answerData.type === "MATCHING").answerMap = materialMap;
5787
+ answer.data.find(
5788
+ (answerData) => answerData.type === "MATCHING"
5789
+ ).answerMap = materialMap;
5782
5790
  }, [showCorrectAnswer, answer, materialMap]);
5783
5791
  (0, import_react21.useEffect)(() => {
5784
- if (!draggedValue || mousePosition.y === 0) return;
5785
- const handleAutoScroll = () => {
5786
- const viewportHeight = window.innerHeight;
5787
- const scrollY = window.scrollY;
5788
- if (mousePosition.y < SCROLL_THRESHOLD + scrollY) {
5789
- window.scrollBy(0, -SCROLL_SPEED);
5790
- } else if (mousePosition.y > viewportHeight + scrollY - SCROLL_THRESHOLD) {
5791
- window.scrollBy(0, SCROLL_SPEED);
5792
- }
5793
- };
5794
- scrollIntervalRef.current = setInterval(handleAutoScroll, 16);
5795
- return () => {
5796
- if (scrollIntervalRef.current) {
5797
- clearInterval(scrollIntervalRef.current);
5798
- }
5799
- };
5800
- }, [draggedValue, mousePosition.y]);
5801
- (0, import_react21.useEffect)(() => {
5802
- if (!draggedValue || touchPosition.y === 0) return;
5803
- const handleAutoScroll = () => {
5804
- const viewportHeight = window.innerHeight;
5805
- const scrollY = window.scrollY;
5806
- if (touchPosition.y < SCROLL_THRESHOLD + scrollY) {
5807
- window.scrollBy(0, -SCROLL_SPEED);
5808
- } else if (touchPosition.y > viewportHeight + scrollY - SCROLL_THRESHOLD) {
5809
- window.scrollBy(0, SCROLL_SPEED);
5810
- }
5811
- };
5812
- scrollIntervalRef.current = setInterval(handleAutoScroll, 16);
5813
- return () => {
5814
- if (scrollIntervalRef.current) {
5815
- clearInterval(scrollIntervalRef.current);
5792
+ if (dropTargetKey && dropZoneRefs.current[dropTargetKey]) {
5793
+ const dropZoneElement = dropZoneRefs.current[dropTargetKey];
5794
+ if (dropZoneElement) {
5795
+ dropZoneElement.scrollIntoView({
5796
+ behavior: "smooth",
5797
+ block: "center"
5798
+ });
5816
5799
  }
5817
- };
5818
- }, [draggedValue, touchPosition.y]);
5800
+ }
5801
+ }, [dropTargetKey]);
5819
5802
  const retrieveAnswerMap = () => {
5820
5803
  const foundIndex = answer.data.findIndex(
5821
5804
  (answerData) => answerData.type === "MATCHING"
@@ -6044,6 +6027,7 @@ var MatchingActivityMaterialContent = ({
6044
6027
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6045
6028
  "div",
6046
6029
  {
6030
+ ref: (el) => dropZoneRefs.current[answerMapKey] = el,
6047
6031
  "data-matching-drop-zone": answerMapKey,
6048
6032
  onMouseEnter: () => draggedValue && setDropTargetKey(answerMapKey),
6049
6033
  onMouseLeave: () => setDropTargetKey(null),
package/dist/index.mjs CHANGED
@@ -5531,16 +5531,22 @@ var MatchingActivityMaterialContent = ({
5531
5531
  const [selectedValue, setSelectedValue] = useState20(null);
5532
5532
  const [draggedValue, setDraggedValue] = useState20(null);
5533
5533
  const [dropTargetKey, setDropTargetKey] = useState20(null);
5534
- const [draggedElement, setDraggedElement] = useState20(null);
5534
+ const [draggedElement, setDraggedElement] = useState20(
5535
+ null
5536
+ );
5535
5537
  const [isShuffled, setIsShuffled] = useState20(false);
5536
5538
  const [shuffledMaterialList, setShuffledMaterialList] = useState20([]);
5537
5539
  const dragElementRef = useRef6(null);
5538
- const [mousePosition, setMousePosition] = useState20({ x: 0, y: 0 });
5539
- const [touchPosition, setTouchPosition] = useState20({ x: 0, y: 0 });
5540
+ const [mousePosition, setMousePosition] = useState20({
5541
+ x: 0,
5542
+ y: 0
5543
+ });
5544
+ const [touchPosition, setTouchPosition] = useState20({
5545
+ x: 0,
5546
+ y: 0
5547
+ });
5540
5548
  const itemsRef = useRef6(null);
5541
- const scrollIntervalRef = useRef6(null);
5542
- const SCROLL_THRESHOLD = 100;
5543
- const SCROLL_SPEED = 10;
5549
+ const dropZoneRefs = useRef6({});
5544
5550
  useEffect11(() => {
5545
5551
  const shuffleArray2 = (array) => {
5546
5552
  if (!isShuffled) {
@@ -5562,44 +5568,21 @@ var MatchingActivityMaterialContent = ({
5562
5568
  }, [materialMap, isShuffled]);
5563
5569
  useEffect11(() => {
5564
5570
  if (!showCorrectAnswer) return;
5565
- answer.data.find((answerData) => answerData.type === "MATCHING").answerMap = materialMap;
5571
+ answer.data.find(
5572
+ (answerData) => answerData.type === "MATCHING"
5573
+ ).answerMap = materialMap;
5566
5574
  }, [showCorrectAnswer, answer, materialMap]);
5567
5575
  useEffect11(() => {
5568
- if (!draggedValue || mousePosition.y === 0) return;
5569
- const handleAutoScroll = () => {
5570
- const viewportHeight = window.innerHeight;
5571
- const scrollY = window.scrollY;
5572
- if (mousePosition.y < SCROLL_THRESHOLD + scrollY) {
5573
- window.scrollBy(0, -SCROLL_SPEED);
5574
- } else if (mousePosition.y > viewportHeight + scrollY - SCROLL_THRESHOLD) {
5575
- window.scrollBy(0, SCROLL_SPEED);
5576
- }
5577
- };
5578
- scrollIntervalRef.current = setInterval(handleAutoScroll, 16);
5579
- return () => {
5580
- if (scrollIntervalRef.current) {
5581
- clearInterval(scrollIntervalRef.current);
5582
- }
5583
- };
5584
- }, [draggedValue, mousePosition.y]);
5585
- useEffect11(() => {
5586
- if (!draggedValue || touchPosition.y === 0) return;
5587
- const handleAutoScroll = () => {
5588
- const viewportHeight = window.innerHeight;
5589
- const scrollY = window.scrollY;
5590
- if (touchPosition.y < SCROLL_THRESHOLD + scrollY) {
5591
- window.scrollBy(0, -SCROLL_SPEED);
5592
- } else if (touchPosition.y > viewportHeight + scrollY - SCROLL_THRESHOLD) {
5593
- window.scrollBy(0, SCROLL_SPEED);
5594
- }
5595
- };
5596
- scrollIntervalRef.current = setInterval(handleAutoScroll, 16);
5597
- return () => {
5598
- if (scrollIntervalRef.current) {
5599
- clearInterval(scrollIntervalRef.current);
5576
+ if (dropTargetKey && dropZoneRefs.current[dropTargetKey]) {
5577
+ const dropZoneElement = dropZoneRefs.current[dropTargetKey];
5578
+ if (dropZoneElement) {
5579
+ dropZoneElement.scrollIntoView({
5580
+ behavior: "smooth",
5581
+ block: "center"
5582
+ });
5600
5583
  }
5601
- };
5602
- }, [draggedValue, touchPosition.y]);
5584
+ }
5585
+ }, [dropTargetKey]);
5603
5586
  const retrieveAnswerMap = () => {
5604
5587
  const foundIndex = answer.data.findIndex(
5605
5588
  (answerData) => answerData.type === "MATCHING"
@@ -5828,6 +5811,7 @@ var MatchingActivityMaterialContent = ({
5828
5811
  /* @__PURE__ */ jsx32("div", { className: "flex-1", children: /* @__PURE__ */ jsx32(
5829
5812
  "div",
5830
5813
  {
5814
+ ref: (el) => dropZoneRefs.current[answerMapKey] = el,
5831
5815
  "data-matching-drop-zone": answerMapKey,
5832
5816
  onMouseEnter: () => draggedValue && setDropTargetKey(answerMapKey),
5833
5817
  onMouseLeave: () => setDropTargetKey(null),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "catchup-library-web",
3
- "version": "1.21.01",
3
+ "version": "1.21.02",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from "react";
2
2
  import ShowMaterialMediaByContentType from "./ShowMaterialMediaByContentType";
3
3
  import { InlineMath } from "react-katex";
4
4
  import { constructInputWithSpecialExpressionList } from "../../../utilization/CatchtivityUtilization";
5
+ import { IMatchingActivityMaterialProps } from "../../../properties/ActivityProperties";
5
6
  import DividerLine from "../../dividers/DividerLine";
6
7
 
7
8
  const MatchingActivityMaterialContent = ({
@@ -13,25 +14,29 @@ const MatchingActivityMaterialContent = ({
13
14
  onChange,
14
15
  isPreview,
15
16
  showCorrectAnswer,
16
- }) => {
17
- const [selectedValue, setSelectedValue] = useState(null);
18
- const [draggedValue, setDraggedValue] = useState(null);
19
- const [dropTargetKey, setDropTargetKey] = useState(null);
20
- const [draggedElement, setDraggedElement] = useState(null);
17
+ }: IMatchingActivityMaterialProps) => {
18
+ const [selectedValue, setSelectedValue] = useState<string | null>(null);
19
+ const [draggedValue, setDraggedValue] = useState<string | null>(null);
20
+ const [dropTargetKey, setDropTargetKey] = useState<string | null>(null);
21
+ const [draggedElement, setDraggedElement] = useState<HTMLElement | null>(
22
+ null
23
+ );
21
24
  const [isShuffled, setIsShuffled] = useState(false);
22
- const [shuffledMaterialList, setShuffledMaterialList] = useState([]);
23
- const dragElementRef = useRef(null);
24
- const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
25
- const [touchPosition, setTouchPosition] = useState({ x: 0, y: 0 });
26
- const itemsRef = useRef(null);
27
- const scrollIntervalRef = useRef(null);
28
-
29
- // Auto-scroll configuration
30
- const SCROLL_THRESHOLD = 100; // Distance from edge to trigger scroll
31
- const SCROLL_SPEED = 10; // Pixels to scroll per interval
25
+ const [shuffledMaterialList, setShuffledMaterialList] = useState<any[]>([]);
26
+ const dragElementRef = useRef<HTMLDivElement>(null);
27
+ const [mousePosition, setMousePosition] = useState<{ x: number; y: number }>({
28
+ x: 0,
29
+ y: 0,
30
+ });
31
+ const [touchPosition, setTouchPosition] = useState<{ x: number; y: number }>({
32
+ x: 0,
33
+ y: 0,
34
+ });
35
+ const itemsRef = useRef<HTMLDivElement>(null);
36
+ const dropZoneRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
32
37
 
33
38
  useEffect(() => {
34
- const shuffleArray = (array) => {
39
+ const shuffleArray = (array: any) => {
35
40
  if (!isShuffled) {
36
41
  const copyArray = JSON.parse(JSON.stringify(array));
37
42
  for (let i = copyArray.length - 1; i > 0; i--) {
@@ -43,7 +48,7 @@ const MatchingActivityMaterialContent = ({
43
48
  }
44
49
  return array;
45
50
  };
46
- const materialList = [];
51
+ const materialList: any = [];
47
52
  Object.keys(materialMap).forEach((materialKey) => {
48
53
  materialList.push(materialMap[materialKey]);
49
54
  });
@@ -52,84 +57,45 @@ const MatchingActivityMaterialContent = ({
52
57
 
53
58
  useEffect(() => {
54
59
  if (!showCorrectAnswer) return;
55
- answer.data.find((answerData) => answerData.type === "MATCHING").answerMap =
56
- materialMap;
60
+ answer.data.find(
61
+ (answerData: any) => answerData.type === "MATCHING"
62
+ ).answerMap = materialMap;
57
63
  }, [showCorrectAnswer, answer, materialMap]);
58
64
 
59
- // Auto-scroll effect for mouse drag
60
- useEffect(() => {
61
- if (!draggedValue || mousePosition.y === 0) return;
62
-
63
- const handleAutoScroll = () => {
64
- const viewportHeight = window.innerHeight;
65
- const scrollY = window.scrollY;
66
-
67
- // Check if near top edge
68
- if (mousePosition.y < SCROLL_THRESHOLD + scrollY) {
69
- window.scrollBy(0, -SCROLL_SPEED);
70
- }
71
- // Check if near bottom edge
72
- else if (mousePosition.y > viewportHeight + scrollY - SCROLL_THRESHOLD) {
73
- window.scrollBy(0, SCROLL_SPEED);
74
- }
75
- };
76
-
77
- scrollIntervalRef.current = setInterval(handleAutoScroll, 16); // ~60fps
78
-
79
- return () => {
80
- if (scrollIntervalRef.current) {
81
- clearInterval(scrollIntervalRef.current);
82
- }
83
- };
84
- }, [draggedValue, mousePosition.y]);
85
-
86
- // Auto-scroll effect for touch drag
65
+ // Auto-scroll to center the drop zone when hovering
87
66
  useEffect(() => {
88
- if (!draggedValue || touchPosition.y === 0) return;
89
-
90
- const handleAutoScroll = () => {
91
- const viewportHeight = window.innerHeight;
92
- const scrollY = window.scrollY;
93
-
94
- // Check if near top edge
95
- if (touchPosition.y < SCROLL_THRESHOLD + scrollY) {
96
- window.scrollBy(0, -SCROLL_SPEED);
97
- }
98
- // Check if near bottom edge
99
- else if (touchPosition.y > viewportHeight + scrollY - SCROLL_THRESHOLD) {
100
- window.scrollBy(0, SCROLL_SPEED);
67
+ if (dropTargetKey && dropZoneRefs.current[dropTargetKey]) {
68
+ const dropZoneElement = dropZoneRefs.current[dropTargetKey];
69
+ if (dropZoneElement) {
70
+ dropZoneElement.scrollIntoView({
71
+ behavior: "smooth",
72
+ block: "center",
73
+ });
101
74
  }
102
- };
103
-
104
- scrollIntervalRef.current = setInterval(handleAutoScroll, 16); // ~60fps
105
-
106
- return () => {
107
- if (scrollIntervalRef.current) {
108
- clearInterval(scrollIntervalRef.current);
109
- }
110
- };
111
- }, [draggedValue, touchPosition.y]);
75
+ }
76
+ }, [dropTargetKey]);
112
77
 
113
78
  const retrieveAnswerMap = () => {
114
79
  const foundIndex = answer.data.findIndex(
115
- (answerData) => answerData.type === "MATCHING"
80
+ (answerData: any) => answerData.type === "MATCHING"
116
81
  );
117
82
  return answer.data[foundIndex].answerMap;
118
83
  };
119
84
 
120
- const retrieveFilteredMaterialList = (answerMap) => {
121
- const selectedValueList = [];
85
+ const retrieveFilteredMaterialList = (answerMap: any) => {
86
+ const selectedValueList: any = [];
122
87
  Object.keys(answerMap).forEach((key) => {
123
88
  selectedValueList.push(answerMap[key]);
124
89
  });
125
90
 
126
91
  return shuffledMaterialList.filter(
127
92
  (material) =>
128
- selectedValueList.findIndex((value) => material === value) === -1
93
+ selectedValueList.findIndex((value: string) => material === value) ===
94
+ -1
129
95
  );
130
96
  };
131
97
 
132
- const checkAnswerState = (correctAnswer, learnerAnswer) => {
98
+ const checkAnswerState = (correctAnswer: string, learnerAnswer: string) => {
133
99
  if (!isPreview) return null;
134
100
  if (!learnerAnswer) return "EMPTY";
135
101
  if (correctAnswer === learnerAnswer) {
@@ -139,7 +105,10 @@ const MatchingActivityMaterialContent = ({
139
105
  };
140
106
 
141
107
  // Mouse drag handlers
142
- const handleMouseDown = (e, materialValue) => {
108
+ const handleMouseDown = (
109
+ e: React.MouseEvent,
110
+ materialValue: string
111
+ ): void => {
143
112
  if (!checkCanAnswerQuestion()) return;
144
113
  e.preventDefault();
145
114
  setDraggedValue(materialValue);
@@ -147,7 +116,7 @@ const MatchingActivityMaterialContent = ({
147
116
  setMousePosition({ x: e.clientX, y: e.clientY });
148
117
  };
149
118
 
150
- const handleMouseMove = (e) => {
119
+ const handleMouseMove = (e: React.MouseEvent): void => {
151
120
  if (!draggedValue) return;
152
121
 
153
122
  setMousePosition({ x: e.clientX, y: e.clientY });
@@ -164,7 +133,7 @@ const MatchingActivityMaterialContent = ({
164
133
  }
165
134
  };
166
135
 
167
- const handleMouseUp = () => {
136
+ const handleMouseUp = (): void => {
168
137
  if (dropTargetKey !== null && draggedValue !== null) {
169
138
  onChange(answer, dropTargetKey, draggedValue);
170
139
  }
@@ -174,7 +143,11 @@ const MatchingActivityMaterialContent = ({
174
143
  };
175
144
 
176
145
  // Touch drag handlers
177
- const handleTouchStart = (e, materialValue, element) => {
146
+ const handleTouchStart = (
147
+ e: React.TouchEvent,
148
+ materialValue: string,
149
+ element: HTMLElement
150
+ ): void => {
178
151
  if (!checkCanAnswerQuestion()) return;
179
152
  const touch = e.touches[0];
180
153
  setDraggedValue(materialValue);
@@ -183,7 +156,7 @@ const MatchingActivityMaterialContent = ({
183
156
  setSelectedValue(null);
184
157
  };
185
158
 
186
- const handleTouchMove = (e) => {
159
+ const handleTouchMove = (e: React.TouchEvent): void => {
187
160
  if (!draggedValue) return;
188
161
 
189
162
  const touch = e.touches[0];
@@ -204,7 +177,7 @@ const MatchingActivityMaterialContent = ({
204
177
  }
205
178
  };
206
179
 
207
- const handleTouchEnd = () => {
180
+ const handleTouchEnd = (): void => {
208
181
  if (dropTargetKey !== null && draggedValue !== null) {
209
182
  onChange(answer, dropTargetKey, draggedValue);
210
183
  }
@@ -215,13 +188,13 @@ const MatchingActivityMaterialContent = ({
215
188
  };
216
189
 
217
190
  // Click/tap to select (for easier mobile interaction)
218
- const handleSelectItem = (materialValue) => {
191
+ const handleSelectItem = (materialValue: string): void => {
219
192
  if (!checkCanAnswerQuestion()) return;
220
193
  setSelectedValue(materialValue);
221
194
  setDraggedValue(null);
222
195
  };
223
196
 
224
- const handleDropZoneClick = (answerMapKey) => {
197
+ const handleDropZoneClick = (answerMapKey: string): void => {
225
198
  if (selectedValue !== null) {
226
199
  onChange(answer, answerMapKey, selectedValue);
227
200
  setSelectedValue(null);
@@ -457,6 +430,7 @@ const MatchingActivityMaterialContent = ({
457
430
  <div className="mx-4 w-[2px] bg-catchup-lighter-gray"></div>
458
431
  <div className="flex-1">
459
432
  <div
433
+ ref={(el) => (dropZoneRefs.current[answerMapKey] = el)}
460
434
  data-matching-drop-zone={answerMapKey}
461
435
  onMouseEnter={() =>
462
436
  draggedValue && setDropTargetKey(answerMapKey)