catchup-library-web 1.21.5 → 1.21.7

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
@@ -5776,7 +5776,8 @@ var MatchingActivityMaterialContent = ({
5776
5776
  });
5777
5777
  const itemsRef = (0, import_react21.useRef)(null);
5778
5778
  const dropZoneRefs = (0, import_react21.useRef)({});
5779
- const scrollIntervalRef = (0, import_react21.useRef)(null);
5779
+ const scrollAnimationRef = (0, import_react21.useRef)(null);
5780
+ const lastScrollTimeRef = (0, import_react21.useRef)(0);
5780
5781
  (0, import_react21.useEffect)(() => {
5781
5782
  const shuffleArray2 = (array) => {
5782
5783
  if (!isShuffled) {
@@ -5802,33 +5803,44 @@ var MatchingActivityMaterialContent = ({
5802
5803
  (answerData) => answerData.type === "MATCHING"
5803
5804
  ).answerMap = materialMap;
5804
5805
  }, [showCorrectAnswer, answer, materialMap]);
5805
- const handleAutoScroll = (clientY) => {
5806
- const scrollThreshold = 100;
5807
- const scrollSpeed = 10;
5808
- const viewportHeight = window.innerHeight;
5809
- if (scrollIntervalRef.current) {
5810
- clearInterval(scrollIntervalRef.current);
5811
- scrollIntervalRef.current = null;
5812
- }
5813
- if (clientY > viewportHeight - scrollThreshold) {
5814
- scrollIntervalRef.current = setInterval(() => {
5815
- window.scrollBy(0, scrollSpeed);
5816
- }, 16);
5817
- } else if (clientY < scrollThreshold) {
5818
- scrollIntervalRef.current = setInterval(() => {
5819
- window.scrollBy(0, -scrollSpeed);
5820
- }, 16);
5821
- }
5822
- };
5823
- const stopAutoScroll = () => {
5824
- if (scrollIntervalRef.current) {
5825
- clearInterval(scrollIntervalRef.current);
5826
- scrollIntervalRef.current = null;
5806
+ (0, import_react21.useEffect)(() => {
5807
+ if (dropTargetKey && dropZoneRefs.current[dropTargetKey]) {
5808
+ const dropZoneElement = dropZoneRefs.current[dropTargetKey];
5809
+ const currentTime = Date.now();
5810
+ if (currentTime - lastScrollTimeRef.current < 300) {
5811
+ return;
5812
+ }
5813
+ lastScrollTimeRef.current = currentTime;
5814
+ if (dropZoneElement) {
5815
+ if (scrollAnimationRef.current) {
5816
+ cancelAnimationFrame(scrollAnimationRef.current);
5817
+ }
5818
+ const targetPosition = dropZoneElement.getBoundingClientRect().top + window.pageYOffset;
5819
+ const startPosition = window.pageYOffset;
5820
+ const distance = targetPosition - startPosition - window.innerHeight / 2 + dropZoneElement.offsetHeight / 2;
5821
+ const duration = 800;
5822
+ let start = null;
5823
+ const animation = (currentTime2) => {
5824
+ if (start === null) start = currentTime2;
5825
+ const timeElapsed = currentTime2 - start;
5826
+ const progress = Math.min(timeElapsed / duration, 1);
5827
+ const ease = (t) => 1 - Math.pow(1 - t, 3);
5828
+ window.scrollTo(0, startPosition + distance * ease(progress));
5829
+ if (timeElapsed < duration) {
5830
+ scrollAnimationRef.current = requestAnimationFrame(animation);
5831
+ } else {
5832
+ scrollAnimationRef.current = null;
5833
+ }
5834
+ };
5835
+ scrollAnimationRef.current = requestAnimationFrame(animation);
5836
+ }
5827
5837
  }
5828
- };
5838
+ }, [dropTargetKey]);
5829
5839
  (0, import_react21.useEffect)(() => {
5830
5840
  return () => {
5831
- stopAutoScroll();
5841
+ if (scrollAnimationRef.current) {
5842
+ cancelAnimationFrame(scrollAnimationRef.current);
5843
+ }
5832
5844
  };
5833
5845
  }, []);
5834
5846
  const retrieveAnswerMap = () => {
@@ -5864,7 +5876,6 @@ var MatchingActivityMaterialContent = ({
5864
5876
  const handleMouseMove = (e) => {
5865
5877
  if (!draggedValue) return;
5866
5878
  setMousePosition({ x: e.clientX, y: e.clientY });
5867
- handleAutoScroll(e.clientY);
5868
5879
  const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
5869
5880
  const dropZone = elementUnder == null ? void 0 : elementUnder.closest("[data-matching-drop-zone]");
5870
5881
  if (dropZone) {
@@ -5875,7 +5886,6 @@ var MatchingActivityMaterialContent = ({
5875
5886
  }
5876
5887
  };
5877
5888
  const handleMouseUp = () => {
5878
- stopAutoScroll();
5879
5889
  if (dropTargetKey !== null && draggedValue !== null) {
5880
5890
  onChange(answer, dropTargetKey, draggedValue);
5881
5891
  }
@@ -5895,7 +5905,6 @@ var MatchingActivityMaterialContent = ({
5895
5905
  if (!draggedValue) return;
5896
5906
  const touch = e.touches[0];
5897
5907
  setTouchPosition({ x: touch.clientX, y: touch.clientY });
5898
- handleAutoScroll(touch.clientY);
5899
5908
  const elementUnder = document.elementFromPoint(
5900
5909
  touch.clientX,
5901
5910
  touch.clientY
@@ -5909,7 +5918,6 @@ var MatchingActivityMaterialContent = ({
5909
5918
  }
5910
5919
  };
5911
5920
  const handleTouchEnd = () => {
5912
- stopAutoScroll();
5913
5921
  if (dropTargetKey !== null && draggedValue !== null) {
5914
5922
  onChange(answer, dropTargetKey, draggedValue);
5915
5923
  }
package/dist/index.mjs CHANGED
@@ -5560,7 +5560,8 @@ var MatchingActivityMaterialContent = ({
5560
5560
  });
5561
5561
  const itemsRef = useRef6(null);
5562
5562
  const dropZoneRefs = useRef6({});
5563
- const scrollIntervalRef = useRef6(null);
5563
+ const scrollAnimationRef = useRef6(null);
5564
+ const lastScrollTimeRef = useRef6(0);
5564
5565
  useEffect11(() => {
5565
5566
  const shuffleArray2 = (array) => {
5566
5567
  if (!isShuffled) {
@@ -5586,33 +5587,44 @@ var MatchingActivityMaterialContent = ({
5586
5587
  (answerData) => answerData.type === "MATCHING"
5587
5588
  ).answerMap = materialMap;
5588
5589
  }, [showCorrectAnswer, answer, materialMap]);
5589
- const handleAutoScroll = (clientY) => {
5590
- const scrollThreshold = 100;
5591
- const scrollSpeed = 10;
5592
- const viewportHeight = window.innerHeight;
5593
- if (scrollIntervalRef.current) {
5594
- clearInterval(scrollIntervalRef.current);
5595
- scrollIntervalRef.current = null;
5596
- }
5597
- if (clientY > viewportHeight - scrollThreshold) {
5598
- scrollIntervalRef.current = setInterval(() => {
5599
- window.scrollBy(0, scrollSpeed);
5600
- }, 16);
5601
- } else if (clientY < scrollThreshold) {
5602
- scrollIntervalRef.current = setInterval(() => {
5603
- window.scrollBy(0, -scrollSpeed);
5604
- }, 16);
5605
- }
5606
- };
5607
- const stopAutoScroll = () => {
5608
- if (scrollIntervalRef.current) {
5609
- clearInterval(scrollIntervalRef.current);
5610
- scrollIntervalRef.current = null;
5590
+ useEffect11(() => {
5591
+ if (dropTargetKey && dropZoneRefs.current[dropTargetKey]) {
5592
+ const dropZoneElement = dropZoneRefs.current[dropTargetKey];
5593
+ const currentTime = Date.now();
5594
+ if (currentTime - lastScrollTimeRef.current < 300) {
5595
+ return;
5596
+ }
5597
+ lastScrollTimeRef.current = currentTime;
5598
+ if (dropZoneElement) {
5599
+ if (scrollAnimationRef.current) {
5600
+ cancelAnimationFrame(scrollAnimationRef.current);
5601
+ }
5602
+ const targetPosition = dropZoneElement.getBoundingClientRect().top + window.pageYOffset;
5603
+ const startPosition = window.pageYOffset;
5604
+ const distance = targetPosition - startPosition - window.innerHeight / 2 + dropZoneElement.offsetHeight / 2;
5605
+ const duration = 800;
5606
+ let start = null;
5607
+ const animation = (currentTime2) => {
5608
+ if (start === null) start = currentTime2;
5609
+ const timeElapsed = currentTime2 - start;
5610
+ const progress = Math.min(timeElapsed / duration, 1);
5611
+ const ease = (t) => 1 - Math.pow(1 - t, 3);
5612
+ window.scrollTo(0, startPosition + distance * ease(progress));
5613
+ if (timeElapsed < duration) {
5614
+ scrollAnimationRef.current = requestAnimationFrame(animation);
5615
+ } else {
5616
+ scrollAnimationRef.current = null;
5617
+ }
5618
+ };
5619
+ scrollAnimationRef.current = requestAnimationFrame(animation);
5620
+ }
5611
5621
  }
5612
- };
5622
+ }, [dropTargetKey]);
5613
5623
  useEffect11(() => {
5614
5624
  return () => {
5615
- stopAutoScroll();
5625
+ if (scrollAnimationRef.current) {
5626
+ cancelAnimationFrame(scrollAnimationRef.current);
5627
+ }
5616
5628
  };
5617
5629
  }, []);
5618
5630
  const retrieveAnswerMap = () => {
@@ -5648,7 +5660,6 @@ var MatchingActivityMaterialContent = ({
5648
5660
  const handleMouseMove = (e) => {
5649
5661
  if (!draggedValue) return;
5650
5662
  setMousePosition({ x: e.clientX, y: e.clientY });
5651
- handleAutoScroll(e.clientY);
5652
5663
  const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
5653
5664
  const dropZone = elementUnder == null ? void 0 : elementUnder.closest("[data-matching-drop-zone]");
5654
5665
  if (dropZone) {
@@ -5659,7 +5670,6 @@ var MatchingActivityMaterialContent = ({
5659
5670
  }
5660
5671
  };
5661
5672
  const handleMouseUp = () => {
5662
- stopAutoScroll();
5663
5673
  if (dropTargetKey !== null && draggedValue !== null) {
5664
5674
  onChange(answer, dropTargetKey, draggedValue);
5665
5675
  }
@@ -5679,7 +5689,6 @@ var MatchingActivityMaterialContent = ({
5679
5689
  if (!draggedValue) return;
5680
5690
  const touch = e.touches[0];
5681
5691
  setTouchPosition({ x: touch.clientX, y: touch.clientY });
5682
- handleAutoScroll(touch.clientY);
5683
5692
  const elementUnder = document.elementFromPoint(
5684
5693
  touch.clientX,
5685
5694
  touch.clientY
@@ -5693,7 +5702,6 @@ var MatchingActivityMaterialContent = ({
5693
5702
  }
5694
5703
  };
5695
5704
  const handleTouchEnd = () => {
5696
- stopAutoScroll();
5697
5705
  if (dropTargetKey !== null && draggedValue !== null) {
5698
5706
  onChange(answer, dropTargetKey, draggedValue);
5699
5707
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "catchup-library-web",
3
- "version": "1.21.05",
3
+ "version": "1.21.07",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -34,7 +34,8 @@ const MatchingActivityMaterialContent = ({
34
34
  });
35
35
  const itemsRef = useRef<HTMLDivElement>(null);
36
36
  const dropZoneRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
37
- const scrollIntervalRef = useRef<number | null>(null);
37
+ const scrollAnimationRef = useRef<number | null>(null);
38
+ const lastScrollTimeRef = useRef<number>(0);
38
39
 
39
40
  useEffect(() => {
40
41
  const shuffleArray = (array: any) => {
@@ -63,43 +64,64 @@ const MatchingActivityMaterialContent = ({
63
64
  ).answerMap = materialMap;
64
65
  }, [showCorrectAnswer, answer, materialMap]);
65
66
 
66
- // Auto-scroll function
67
- const handleAutoScroll = (clientY: number) => {
68
- const scrollThreshold = 100; // Distance from edge to trigger scroll
69
- const scrollSpeed = 10; // Pixels to scroll per interval
70
- const viewportHeight = window.innerHeight;
67
+ // Replace the useEffect with this version
68
+ useEffect(() => {
69
+ if (dropTargetKey && dropZoneRefs.current[dropTargetKey]) {
70
+ const dropZoneElement = dropZoneRefs.current[dropTargetKey];
71
+ const currentTime = Date.now();
71
72
 
72
- // Clear existing interval
73
- if (scrollIntervalRef.current) {
74
- clearInterval(scrollIntervalRef.current);
75
- scrollIntervalRef.current = null;
76
- }
73
+ // Throttle: only scroll every 300ms to slow it down
74
+ if (currentTime - lastScrollTimeRef.current < 300) {
75
+ return;
76
+ }
77
77
 
78
- // Scroll down when near bottom
79
- if (clientY > viewportHeight - scrollThreshold) {
80
- scrollIntervalRef.current = setInterval(() => {
81
- window.scrollBy(0, scrollSpeed);
82
- }, 16); // ~60fps
83
- }
84
- // Scroll up when near top
85
- else if (clientY < scrollThreshold) {
86
- scrollIntervalRef.current = setInterval(() => {
87
- window.scrollBy(0, -scrollSpeed);
88
- }, 16);
89
- }
90
- };
78
+ lastScrollTimeRef.current = currentTime;
91
79
 
92
- const stopAutoScroll = () => {
93
- if (scrollIntervalRef.current) {
94
- clearInterval(scrollIntervalRef.current);
95
- scrollIntervalRef.current = null;
80
+ if (dropZoneElement) {
81
+ // Cancel any existing animation
82
+ if (scrollAnimationRef.current) {
83
+ cancelAnimationFrame(scrollAnimationRef.current);
84
+ }
85
+
86
+ const targetPosition =
87
+ dropZoneElement.getBoundingClientRect().top + window.pageYOffset;
88
+ const startPosition = window.pageYOffset;
89
+ const distance =
90
+ targetPosition -
91
+ startPosition -
92
+ window.innerHeight / 2 +
93
+ dropZoneElement.offsetHeight / 2;
94
+ const duration = 800; // Slower duration
95
+ let start: number | null = null;
96
+
97
+ const animation = (currentTime: number) => {
98
+ if (start === null) start = currentTime;
99
+ const timeElapsed = currentTime - start;
100
+ const progress = Math.min(timeElapsed / duration, 1);
101
+
102
+ // Gentler easing function
103
+ const ease = (t: number) => 1 - Math.pow(1 - t, 3);
104
+
105
+ window.scrollTo(0, startPosition + distance * ease(progress));
106
+
107
+ if (timeElapsed < duration) {
108
+ scrollAnimationRef.current = requestAnimationFrame(animation);
109
+ } else {
110
+ scrollAnimationRef.current = null;
111
+ }
112
+ };
113
+
114
+ scrollAnimationRef.current = requestAnimationFrame(animation);
115
+ }
96
116
  }
97
- };
117
+ }, [dropTargetKey]);
98
118
 
99
- // Cleanup on unmount
119
+ // Add cleanup on unmount
100
120
  useEffect(() => {
101
121
  return () => {
102
- stopAutoScroll();
122
+ if (scrollAnimationRef.current) {
123
+ cancelAnimationFrame(scrollAnimationRef.current);
124
+ }
103
125
  };
104
126
  }, []);
105
127
 
@@ -149,9 +171,6 @@ const MatchingActivityMaterialContent = ({
149
171
 
150
172
  setMousePosition({ x: e.clientX, y: e.clientY });
151
173
 
152
- // Handle auto-scroll
153
- handleAutoScroll(e.clientY);
154
-
155
174
  // Find the element under the mouse point
156
175
  const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
157
176
  const dropZone = elementUnder?.closest("[data-matching-drop-zone]");
@@ -165,7 +184,6 @@ const MatchingActivityMaterialContent = ({
165
184
  };
166
185
 
167
186
  const handleMouseUp = (): void => {
168
- stopAutoScroll();
169
187
  if (dropTargetKey !== null && draggedValue !== null) {
170
188
  onChange(answer, dropTargetKey, draggedValue);
171
189
  }
@@ -194,9 +212,6 @@ const MatchingActivityMaterialContent = ({
194
212
  const touch = e.touches[0];
195
213
  setTouchPosition({ x: touch.clientX, y: touch.clientY });
196
214
 
197
- // Handle auto-scroll
198
- handleAutoScroll(touch.clientY);
199
-
200
215
  // Find the element under the touch point
201
216
  const elementUnder = document.elementFromPoint(
202
217
  touch.clientX,
@@ -213,7 +228,6 @@ const MatchingActivityMaterialContent = ({
213
228
  };
214
229
 
215
230
  const handleTouchEnd = (): void => {
216
- stopAutoScroll();
217
231
  if (dropTargetKey !== null && draggedValue !== null) {
218
232
  onChange(answer, dropTargetKey, draggedValue);
219
233
  }