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.
- package/components/Popup.svelte +30 -13
- package/package.json +1 -1
package/components/Popup.svelte
CHANGED
|
@@ -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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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)
|
|
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;
|