openguessr-ui 0.4.0 → 0.5.1
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/README.md +2 -0
- package/base.css +1 -0
- package/components/Popup.svelte +3 -4
- package/package.json +1 -1
- package/utils/tooltip.svelte.js +48 -0
package/README.md
CHANGED
|
@@ -441,6 +441,8 @@ Options:
|
|
|
441
441
|
- `zIndex`: Tooltip z-index
|
|
442
442
|
- `mobile`: Set to false to hide the tooltip on mobile
|
|
443
443
|
|
|
444
|
+
Tooltips with automatic state handling are shown on hover (and on long-press with touch input).
|
|
445
|
+
|
|
444
446
|
## Sound effects
|
|
445
447
|
|
|
446
448
|
UI sound effects are available as `.ogg` files and can be played with any audio library. The `sounds` export maps each name to its file URL:
|
package/base.css
CHANGED
package/components/Popup.svelte
CHANGED
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
// Drawer logic ------------------------------------------------------------------------------------
|
|
60
60
|
|
|
61
61
|
// Bindings
|
|
62
|
-
let contentEl = $state();
|
|
63
62
|
let uiWindowHeight = $state();
|
|
64
63
|
|
|
65
64
|
// Drawer state
|
|
@@ -93,7 +92,7 @@
|
|
|
93
92
|
|
|
94
93
|
const dragStart = (event) => {
|
|
95
94
|
// 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,
|
|
95
|
+
if (!popupToDrawer.current || dragStartY != null || isScrolledDown(event.target, event.currentTarget)) return; // Current target is ui-window
|
|
97
96
|
|
|
98
97
|
// Catch the drawer where it is (could still be animating open)
|
|
99
98
|
cancelAnimationFrame(openAnimationFrame);
|
|
@@ -118,7 +117,7 @@
|
|
|
118
117
|
|
|
119
118
|
// Dragging finger upwards while the touched element (or an ancestor up to the content) can still scroll down
|
|
120
119
|
// 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,
|
|
120
|
+
const isScrollingDown = eventY <= dragStartY && canScrollDown(event.target, event.currentTarget); // Current target is ui-window
|
|
122
121
|
|
|
123
122
|
if (isScrollingHorizontally || isScrollingDown) {
|
|
124
123
|
dragStartY = null;
|
|
@@ -258,7 +257,7 @@
|
|
|
258
257
|
<button class="close-popup-button standard-button" aria-label="close" onclick={close}
|
|
259
258
|
><X strokeWidth={2.25} /></button
|
|
260
259
|
>
|
|
261
|
-
<div class="content of-top of-bottom" class:content-frameless={frameless}
|
|
260
|
+
<div class="content of-top of-bottom" class:content-frameless={frameless}>
|
|
262
261
|
{@render children?.()}
|
|
263
262
|
</div>
|
|
264
263
|
</div>
|
package/package.json
CHANGED
package/utils/tooltip.svelte.js
CHANGED
|
@@ -6,6 +6,8 @@ export function tooltip({ text, imageSrc, imageAspectRatio = "1 / 1", state, onc
|
|
|
6
6
|
let visible = false;
|
|
7
7
|
let cleanupAutoUpdate;
|
|
8
8
|
let showTimeout = null;
|
|
9
|
+
let longPressTimeout = null;
|
|
10
|
+
let suppressClick = false;
|
|
9
11
|
|
|
10
12
|
const persistent = Boolean(state);
|
|
11
13
|
const closedScale = imageSrc ? 0.85 : 0;
|
|
@@ -157,6 +159,43 @@ export function tooltip({ text, imageSrc, imageAspectRatio = "1 / 1", state, onc
|
|
|
157
159
|
hide();
|
|
158
160
|
}
|
|
159
161
|
|
|
162
|
+
// On touch devices, a long press shows the tooltip
|
|
163
|
+
function onPointerDown(e) {
|
|
164
|
+
suppressClick = false;
|
|
165
|
+
if (e.pointerType != "touch" || !e.isPrimary) return;
|
|
166
|
+
|
|
167
|
+
// Close the tooltip on any click or other pointer down (scroll, swipe...)
|
|
168
|
+
const closeLongPressTooltip = () => {
|
|
169
|
+
suppressClick = false;
|
|
170
|
+
hide();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// After the 500ms timeout, the tooltip is shown
|
|
174
|
+
clearTimeout(longPressTimeout);
|
|
175
|
+
longPressTimeout = setTimeout(() => {
|
|
176
|
+
if (!visible) show();
|
|
177
|
+
if (visible) {
|
|
178
|
+
suppressClick = true;
|
|
179
|
+
document.addEventListener('pointerdown', closeLongPressTooltip, { capture: true, once: true });
|
|
180
|
+
}
|
|
181
|
+
}, 500);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// On pointerup, and pointercancel since cancel can be e.g. a scroll starting
|
|
185
|
+
function cancelLongPress() {
|
|
186
|
+
clearTimeout(longPressTimeout);
|
|
187
|
+
longPressTimeout = null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Don't trigger the element's click action after a long press
|
|
191
|
+
function onClick(e) {
|
|
192
|
+
cancelLongPress(); // Pointerup doesn't fire reliably with clicks (especialy on WK)
|
|
193
|
+
if (!suppressClick) return hide(); // The click may change what's under the cursor (e.g. a new page) without a pointerleave until the mouse moves
|
|
194
|
+
suppressClick = false;
|
|
195
|
+
e.preventDefault();
|
|
196
|
+
e.stopImmediatePropagation();
|
|
197
|
+
}
|
|
198
|
+
|
|
160
199
|
if (persistent) {
|
|
161
200
|
$effect(() => {
|
|
162
201
|
if (state.visible) scheduleShow();
|
|
@@ -165,13 +204,22 @@ export function tooltip({ text, imageSrc, imageAspectRatio = "1 / 1", state, onc
|
|
|
165
204
|
} else {
|
|
166
205
|
node.addEventListener('pointerenter', onPointerEnter);
|
|
167
206
|
node.addEventListener('pointerleave', onPointerLeave);
|
|
207
|
+
node.addEventListener('pointerdown', onPointerDown);
|
|
208
|
+
node.addEventListener('pointerup', cancelLongPress);
|
|
209
|
+
node.addEventListener('pointercancel', cancelLongPress);
|
|
210
|
+
node.addEventListener('click', onClick, true);
|
|
168
211
|
}
|
|
169
212
|
|
|
170
213
|
return () => {
|
|
171
214
|
if (!persistent) {
|
|
172
215
|
node.removeEventListener('pointerenter', onPointerEnter);
|
|
173
216
|
node.removeEventListener('pointerleave', onPointerLeave);
|
|
217
|
+
node.removeEventListener('pointerdown', onPointerDown);
|
|
218
|
+
node.removeEventListener('pointerup', cancelLongPress);
|
|
219
|
+
node.removeEventListener('pointercancel', cancelLongPress);
|
|
220
|
+
node.removeEventListener('click', onClick, true);
|
|
174
221
|
}
|
|
222
|
+
if (longPressTimeout) clearTimeout(longPressTimeout);
|
|
175
223
|
if (showTimeout) clearTimeout(showTimeout);
|
|
176
224
|
cleanupAutoUpdate?.();
|
|
177
225
|
tooltipElement?.remove();
|