diff --git a/cspell.json b/cspell.json
index 6c381b4df..f6b95d920 100644
--- a/cspell.json
+++ b/cspell.json
@@ -151,6 +151,7 @@
"ParamagicDev",
"peta",
"petabit",
+ "pointercancel",
"Preact",
"preconnect",
"prerendered",
@@ -204,6 +205,8 @@
"thead",
"Themer",
"tinycolor",
+ "touchcancel",
+ "touchend",
"transitionend",
"treeitem",
"treeshaking",
diff --git a/packages/webawesome/docs/docs/resources/changelog.md b/packages/webawesome/docs/docs/resources/changelog.md
index 012763d8d..05f68487d 100644
--- a/packages/webawesome/docs/docs/resources/changelog.md
+++ b/packages/webawesome/docs/docs/resources/changelog.md
@@ -14,6 +14,8 @@ Components with the Experimental badge sh
## Next
- Fixed a bug in `` that prevented the listbox from opening when options were preselected [issue:1883]
+- Fixed a bug in draggable elements that caused a TypeError on `touchend` events when `event.touches` was empty
+- Added `pointercancel` and `touchcancel` event handling to draggable elements to prevent drags from getting stuck
## 3.1.0
diff --git a/packages/webawesome/src/internal/drag.ts b/packages/webawesome/src/internal/drag.ts
index 10c249884..018e318f7 100644
--- a/packages/webawesome/src/internal/drag.ts
+++ b/packages/webawesome/src/internal/drag.ts
@@ -99,20 +99,24 @@ export class DraggableElement {
document.addEventListener('pointerup', this.handleDragStop);
document.addEventListener('pointermove', this.handleDragMove);
+ document.addEventListener('pointercancel', this.handleDragStop);
document.addEventListener('touchend', this.handleDragStop);
document.addEventListener('touchmove', this.handleDragMove);
+ document.addEventListener('touchcancel', this.handleDragStop);
this.options.start(clientX, clientY);
};
private handleDragStop = (event: PointerEvent | TouchEvent) => {
- const clientX = 'touches' in event ? event.touches[0].clientX : (event as PointerEvent).clientX;
- const clientY = 'touches' in event ? event.touches[0].clientY : (event as PointerEvent).clientY;
+ const clientX = 'changedTouches' in event ? event.changedTouches[0].clientX : (event as PointerEvent).clientX;
+ const clientY = 'changedTouches' in event ? event.changedTouches[0].clientY : (event as PointerEvent).clientY;
this.isDragging = false;
document.removeEventListener('pointerup', this.handleDragStop);
document.removeEventListener('pointermove', this.handleDragMove);
+ document.removeEventListener('pointercancel', this.handleDragStop);
document.removeEventListener('touchend', this.handleDragStop);
document.removeEventListener('touchmove', this.handleDragMove);
+ document.removeEventListener('touchcancel', this.handleDragStop);
this.options.stop(clientX, clientY);
};
@@ -141,8 +145,10 @@ export class DraggableElement {
public stop() {
document.removeEventListener('pointerup', this.handleDragStop);
document.removeEventListener('pointermove', this.handleDragMove);
+ document.removeEventListener('pointercancel', this.handleDragStop);
document.removeEventListener('touchend', this.handleDragStop);
document.removeEventListener('touchmove', this.handleDragMove);
+ document.removeEventListener('touchcancel', this.handleDragStop);
this.element.removeEventListener('pointerdown', this.handleDragStart);
if (supportsTouch) {
this.element.removeEventListener('touchstart', this.handleDragStart);