openguessr-ui 0.3.3 → 0.3.5

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.
@@ -63,7 +63,9 @@
63
63
  let uiWindowHeight = $state();
64
64
 
65
65
  // Drawer state
66
+ let dragTouchId;
66
67
  let dragStartY = $state();
68
+ let dragStartX;
67
69
  let dragStartVerticalOffset;
68
70
  let isDragging = $state(false);
69
71
  let drawerVerticalOffset = $state(0);
@@ -86,27 +88,42 @@
86
88
  openAnimationFrame = requestAnimationFrame(step);
87
89
  };
88
90
 
91
+ // Check if the touch that started the drag is included
92
+ const findDragTouch = (touches) => [...touches].find((touch) => touch.identifier === dragTouchId);
93
+
89
94
  const dragStart = (event) => {
90
- // Abort if not a drawer, or if content should be scrolled by the "finger downwards" movement because it isn't scrolled all the way up
91
- if (!popupToDrawer.current || isScrolledDown(event.target, contentEl)) return;
95
+ // Abort if not a drawer, already tracking a finger, or if content should be scrolled by the "finger downwards" movement because it isn't scrolled all the way up
96
+ if (!popupToDrawer.current || dragStartY != null || isScrolledDown(event.target, contentEl)) return;
92
97
 
93
98
  // Catch the drawer where it is (could still be animating open)
94
99
  cancelAnimationFrame(openAnimationFrame);
100
+ const touch = event.changedTouches[0]; // Changed touches lists only new touches, not ones "still" on screen
101
+ dragTouchId = touch.identifier;
95
102
  dragStartVerticalOffset = drawerVerticalOffset;
96
- dragStartY = event.touches[0].clientY;
103
+ dragStartY = touch.clientY;
104
+ dragStartX = touch.clientX;
97
105
  velocitySamples = [{ y: dragStartY, time: performance.now() }];
98
106
  };
99
107
 
100
108
  const drag = (event) => {
101
- if (dragStartY == null) return;
109
+ const touch = findDragTouch(event.touches);
110
+ if (dragStartY == null || !touch) return;
111
+
112
+ const eventY = touch.clientY;
113
+
114
+ // On the first move, decide whether the gesture drags the drawer or scrolls the content
115
+ if (!isDragging) {
116
+ // Horizontal movements belong to the content, e.g. horizontally scrolling elements
117
+ const isScrollingHorizontally = Math.abs(touch.clientX - dragStartX) > Math.abs(eventY - dragStartY); // Check if more horizontal movement than vertical
102
118
 
103
- const eventY = event.touches[0].clientY;
119
+ // Dragging finger upwards while the touched element (or an ancestor up to the content) can still scroll down
120
+ // Mainly relevant for the slow stretch animation when the drwaer is dragged upwards (which shouldn't show when content is scrolled down)
121
+ const isScrollingDown = eventY <= dragStartY && canScrollDown(event.target, contentEl);
104
122
 
105
- // Cancel if dragging finger upwards while the touched element (or an ancestor up to the content) can still scroll down
106
- // Mainly relevant for the slow stretch animation when the drwaer is dragged upwards (which shouldn't show when content is scrolled down)
107
- if (!isDragging && eventY <= dragStartY && canScrollDown(event.target, contentEl)) {
108
- dragStartY = null;
109
- return animateDrawerOpen(); // Touch could've stopped the drawer during open, since it's a content scroll not a drag, resume
123
+ if (isScrollingHorizontally || isScrollingDown) {
124
+ dragStartY = null;
125
+ return animateDrawerOpen(); // Touch could've stopped the drawer during open, since it's a content scroll not a drag, resume
126
+ }
110
127
  }
111
128
 
112
129
  event.preventDefault(); // Prevent page scroll
@@ -122,8 +139,8 @@
122
139
  drawerVerticalOffset = delta > 0 ? delta : delta * 0.05; // Allow dragging the drawer upwards, but make it less effective (that's what the x0.05 is for)
123
140
  };
124
141
 
125
- const dragEnd = () => {
126
- if (dragStartY == null) return;
142
+ const dragEnd = (event) => {
143
+ if (dragStartY == null || !findDragTouch(event.changedTouches)) return; // Only the dragging finger ends the drag
127
144
  dragStartY = null;
128
145
 
129
146
  if (!isDragging) return animateDrawerOpen(); // Single tap without drag, resume opening if it was caught mid-animation
@@ -340,7 +357,7 @@
340
357
  width: 100%;
341
358
  /* Max height is also shorter by the negative --layout-spacer margin bottom */
342
359
  max-height: calc(100dvh - env(safe-area-inset-top));
343
- padding-bottom: calc(var(--window-padding) + env(safe-area-inset-bottom) + var(--layout-spacer));
360
+ padding-bottom: calc(max(var(--window-padding), env(safe-area-inset-bottom)) + var(--layout-spacer));
344
361
  margin-bottom: calc(-1 * var(--layout-spacer));
345
362
  border-bottom-left-radius: 0;
346
363
  border-bottom-right-radius: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openguessr-ui",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite example"