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);