diff --git a/package.json b/package.json index 2ceb3f0..f639c00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@travelopia/web-components", - "version": "0.7.2", + "version": "0.7.3", "description": "Accessible web components for the modern web", "files": [ "dist" diff --git a/src/lightbox/README.md b/src/lightbox/README.md index 33d25d2..e7fdcf6 100644 --- a/src/lightbox/README.md +++ b/src/lightbox/README.md @@ -20,7 +20,7 @@ Example: First, create the lightbox and give it an ID. Style as needed: ```html - + <-- There must be a button inside this component. @@ -53,6 +53,8 @@ Next, we need to trigger the lightbox with and give it some content. Any content | Attribute | Required | Values | Notes | |------------------------|-----------|----------|----------------------------------------------| | close-on-overlay-click | No | `yes` | Closes the modal when the overlay is clicked | +| swipe | No | `yes` | Enables swiping | +| swipe-threshold | No | `200` | Prevent swiping if more than this is swiped | ## Events diff --git a/src/lightbox/index.html b/src/lightbox/index.html index a6da0cd..124dbe3 100644 --- a/src/lightbox/index.html +++ b/src/lightbox/index.html @@ -11,7 +11,7 @@
- + diff --git a/src/lightbox/tp-lightbox.ts b/src/lightbox/tp-lightbox.ts index 27419dd..99e5590 100644 --- a/src/lightbox/tp-lightbox.ts +++ b/src/lightbox/tp-lightbox.ts @@ -17,6 +17,10 @@ export class TPLightboxElement extends HTMLElement { protected currentTemplate: HTMLTemplateElement | null = null; protected currentGroup: string = ''; protected allGroups: NodeListOf | null = null; + protected touchStartX: number = 0; + protected touchStartY: number = 0; + protected swipeThreshold: number = 200; + protected dialogElement: HTMLDialogElement | null; /** * Constructor. @@ -25,8 +29,13 @@ export class TPLightboxElement extends HTMLElement { // Initialize parent. super(); + // Initialize + this.dialogElement = this.querySelector( 'dialog' ); + // Event listeners. - this.querySelector( 'dialog' )?.addEventListener( 'click', this.handleDialogClick.bind( this ) ); + this.dialogElement?.addEventListener( 'click', this.handleDialogClick.bind( this ) ); + this.dialogElement?.addEventListener( 'touchstart', this.handleTouchStart.bind( this ) ); + this.dialogElement?.addEventListener( 'touchend', this.handleTouchEnd.bind( this ) ); } /** @@ -412,4 +421,65 @@ export class TPLightboxElement extends HTMLElement { this.close(); } } + + /** + * Handles the touch start event. + * + * @param { TouchEvent } evt The touch event. + */ + handleTouchStart( evt: TouchEvent ): void { + // Check if we should allow swiping? + if ( 'yes' !== this.getAttribute( 'swipe' ) ) { + // Nope. + return; + } + + // Set the start points. + this.touchStartX = evt.touches[ 0 ].clientX; + this.touchStartY = evt.touches[ 0 ].clientY; + } + + /** + * Handles the touch end event. + * + * @param { TouchEvent } evt The touch event. + */ + handleTouchEnd( evt: TouchEvent ): void { + // Check if we should allow swiping? + if ( 'yes' !== this.getAttribute( 'swipe' ) ) { + // Nope. + return; + } + + // Calculate the distances. + const touchEndX: number = evt.changedTouches[ 0 ].clientX; + const touchEndY: number = evt.changedTouches[ 0 ].clientY; + const swipeDistanceX: number = touchEndX - this.touchStartX; + const swipeDistanceY: number = touchEndY - this.touchStartY; + + // Is this horizontal swipe? + const isHorizontalSwipe = Math.abs( swipeDistanceX ) > Math.abs( swipeDistanceY ); + + // Check if this was a horizontal swipe? + if ( ! isHorizontalSwipe ) { + // Bail. + return; + } + + // Swipe settings + this.swipeThreshold = Number( this.getAttribute( 'swipe-threshold' ) ?? '200' ); + + // Check if it's a right or left swipe. + if ( swipeDistanceX > 0 ) { + // Right-Swipe: Check if horizontal swipe distance is less than the threshold. + if ( swipeDistanceX < this.swipeThreshold ) { + this.previous(); + } + } else if ( swipeDistanceX < 0 ) { + // Left-Swipe: Check if horizontal swipe distance is less than the threshold. + if ( swipeDistanceX > -this.swipeThreshold ) { + this.next(); + } + } + } }