diff --git a/index.html b/index.html
index 8e49ce8..f07d154 100644
--- a/index.html
+++ b/index.html
@@ -2,7 +2,7 @@
-
+
Hive Commons
@@ -817,7 +817,12 @@ Thanks to the organizations that power Hive Commons<
pointerStartX = e.clientX;
pointerStartY = e.clientY;
}, { passive: true });
+ root.addEventListener('pointercancel', function () {
+ pointerStartX = null;
+ pointerStartY = null;
+ }, { passive: true });
root.addEventListener('pointerup', function (e) {
+ if (e.pointerType === 'mouse') return;
if (pointerStartX === null || pointerStartY === null) return;
var dx = e.clientX - pointerStartX;
var dy = e.clientY - pointerStartY;
diff --git a/scripts/carousels.test.mjs b/scripts/carousels.test.mjs
index 357efb2..1e9f678 100644
--- a/scripts/carousels.test.mjs
+++ b/scripts/carousels.test.mjs
@@ -500,6 +500,21 @@ test("hero swipe: touch swipe past threshold navigates; mouse drags, short and v
assertHeroSlide(t, 0);
});
+test("hero swipe: pointercancel clears the swipe start; mouse pointerup never completes a touch gesture", () => {
+ const t = bootHero();
+ t.root.dispatch("pointerdown", { pointerType: "touch", clientX: 300, clientY: 100 });
+ t.root.dispatch("pointercancel", { pointerType: "touch" });
+ t.root.dispatch("pointerup", { pointerType: "mouse", clientX: -500, clientY: 100 });
+ assertHeroSlide(t, 0, "mouse pointerup after a cancelled touch is not a swipe");
+ t.root.dispatch("pointerdown", { pointerType: "touch", clientX: 300, clientY: 100 });
+ t.root.dispatch("pointercancel", { pointerType: "touch" });
+ t.root.dispatch("pointerup", { pointerType: "touch", clientX: 300 - HERO_SWIPE_PX, clientY: 100 });
+ assertHeroSlide(t, 0, "cancelled gesture does not complete");
+ t.root.dispatch("pointerdown", { pointerType: "touch", clientX: 300, clientY: 100 });
+ t.root.dispatch("pointerup", { pointerType: "mouse", clientX: 300 - HERO_SWIPE_PX, clientY: 100 });
+ assertHeroSlide(t, 0, "mouse pointerup beyond threshold is ignored");
+});
+
test("hero deep link: location.hash selects the initial slide; unknown hash falls back to the first", () => {
const t = bootHero({ hash: "#" + HERO_IDS[2] });
assertHeroSlide(t, 2);