1import { getRequiredElement } from "./utilities.js?v=2.2.2.0"; 2 3const GestureDirection = { 4 none: 0, 5 left: 1, 6 right: 2, 7 up: 4, 8 down: 8 9}; 10 11const GestureTouchAction = { 12 auto: 0, 13 none: 1, 14 panX: 2, 15 panY: 3, 16 manipulation: 4 17}; 18 19let _instances = []; 20 21export function initialize(dotnetAdapter, element, elementId, options) { 22 element = getRequiredElement(element, elementId); 23 24 if (!element) 25 return; 26 27 destroy(element, elementId); 28 29 const instance = { 30 dotnetAdapter: dotnetAdapter, 31 element: element, 32 elementId: elementId, 33 options: normalizeOptions(options), 34 originalTouchAction: element.style.touchAction || "", 35 active: false, 36 pointerId: null, 37 startClientX: 0, 38 startClientY: 0, 39 startTime: 0, 40 lastClientX: 0, 41 lastClientY: 0, 42 pointerType: "", 43 longPressTimer: null, 44 longPressFired: false, 45 lastMoveNotification: 0, 46 onPointerDown: null, 47 onPointerMove: null, 48 onPointerUp: null, 49 onPointerCancel: null, 50 onDragStart: null 51 }; 52 53 instance.onPointerDown = (e) => pointerDownHandler(instance, e); 54 instance.onPointerMove = (e) => pointerMoveHandler(instance, e); 55 instance.onPointerUp = (e) => pointerUpHandler(instance, e, false); 56 instance.onPointerCancel = (e) => pointerUpHandler(instance, e, true); 57 instance.onDragStart = (e) => dragStartHandler(instance, e); 58 59 element.addEventListener("pointerdown", instance.onPointerDown); 60 element.addEventListener("pointermove", instance.onPointerMove); 61 element.addEventListener("pointerup", instance.onPointerUp); 62 element.addEventListener("pointercancel", instance.onPointerCancel); 63 element.addEventListener("dragstart", instance.onDragStart); 64 65 applyTouchAction(instance); 66 67 _instances[elementId] = instance; 68} 69 70export function updateOptions(element, elementId, options) { 71 const instance = _instances[elementId]; 72 73 if (!instance) 74 return; 75 76 instance.options = normalizeOptions(options); 77 78 applyTouchAction(instance); 79} 80 81export function destroy(element, elementId) { 82 const instance = _instances[elementId]; 83 84 if (!instance) 85 return; 86 87 if (instance.element) { 88 instance.element.removeEventListener("pointerdown", instance.onPointerDown); 89 instance.element.removeEventListener("pointermove", instance.onPointerMove); 90 instance.element.removeEventListener("pointerup", instance.onPointerUp); 91 instance.element.removeEventListener("pointercancel", instance.onPointerCancel); 92 instance.element.removeEventListener("dragstart", instance.onDragStart); 93 instance.element.style.touchAction = instance.originalTouchAction; 94 } 95 96 clearLongPressTimer(instance); 97 98 instance.dotnetAdapter = null; 99 instance.element = null; 100 101 delete _instances[elementId]; 102} 103 104function pointerDownHandler(instance, e) { 105 if (instance.options.disabled || !instance.dotnetAdapter) 106 return; 107 108 if (e.isPrimary === false) 109 return; 110 111 if (e.pointerType === "mouse" && e.button !== 0) 112 return; 113 114 if (isInteractiveElement(e.target, instance.element)) 115 return; 116 117 instance.active = true; 118 instance.pointerId = e.pointerId; 119 instance.startClientX = e.clientX; 120 instance.startClientY = e.clientY; 121 instance.startTime = e.timeStamp; 122 instance.lastClientX = e.clientX; 123 instance.lastClientY = e.clientY; 124 instance.pointerType = e.pointerType || ""; 125 instance.longPressFired = false; 126 instance.lastMoveNotification = 0; 127 128 if (instance.element.setPointerCapture) { 129 try { 130 instance.element.setPointerCapture(e.pointerId); 131 } 132 catch { 133 } 134 } 135 136 if (instance.options.notifyGestureStarted) { 137 instance.dotnetAdapter.invokeMethodAsync("OnGestureStarted", createGestureArgs(instance, e, GestureDirection.none, false)); 138 } 139 140 startLongPressTimer(instance); 141} 142 143function dragStartHandler(instance, e) { 144 if (instance.options.disabled || !instance.options.preventNativeDrag) 145 return; 146 147 if (isInteractiveElement(e.target, instance.element)) 148 return; 149 150 e.preventDefault(); 151} 152 153function pointerMoveHandler(instance, e) { 154 if (!instance.active || e.pointerId !== instance.pointerId) 155 return; 156 157 if (instance.options.disabled) { 158 resetGesture(instance, e); 159 return; 160 } 161 162 instance.lastClientX = e.clientX; 163 instance.lastClientY = e.clientY; 164 165 if (getDistance(e.clientX - instance.startClientX, e.clientY - instance.startClientY) > instance.options.longPressMoveTolerance) { 166 clearLongPressTimer(instance); 167 } 168 169 if (!instance.options.notifyGestureMoved) 170 return; 171 172 const throttleInterval = Math.max(instance.options.moveThrottleInterval || 0, 0); 173 174 if (throttleInterval > 0 && e.timeStamp - instance.lastMoveNotification < throttleInterval) 175 return; 176 177 instance.lastMoveNotification = e.timeStamp; 178 179 const direction = resolveDirection(e.clientX - instance.startClientX, e.clientY - instance.startClientY); 180 181 instance.dotnetAdapter.invokeMethodAsync("OnGestureMoved", createGestureArgs(instance, e, direction, false)); 182} 183 184function pointerUpHandler(instance, e, canceled) { 185 if (!instance.active || e.pointerId !== instance.pointerId) 186 return; 187 188 clearLongPressTimer(instance); 189 190 const direction = resolveDirection(e.clientX - instance.startClientX, e.clientY - instance.startClientY); 191 const gestureArgs = createGestureArgs(instance, e, direction, canceled); 192 const swipe = !canceled && !instance.options.disabled && !instance.longPressFired && isSwipe(instance, gestureArgs); 193 194 if (instance.options.notifyGestureEnded) { 195 instance.dotnetAdapter.invokeMethodAsync("OnGestureEnded", gestureArgs); 196 } 197 198 if (swipe && instance.options.notifySwiped) { 199 instance.dotnetAdapter.invokeMethodAsync("OnSwiped", gestureArgs); 200 } 201 else if (!canceled && !instance.options.disabled && !instance.longPressFired && instance.options.notifyTapped && isTap(instance, gestureArgs)) { 202 instance.dotnetAdapter.invokeMethodAsync("OnTapped", gestureArgs); 203 } 204 205 resetGesture(instance, e); 206} 207 208function resetGesture(instance, e) { 209 clearLongPressTimer(instance); 210 211 if (instance.element && instance.element.releasePointerCapture && instance.pointerId !== null) { 212 try { 213 instance.element.releasePointerCapture(instance.pointerId); 214 } 215 catch { 216 } 217 } 218 219 instance.active = false; 220 instance.pointerId = null; 221 instance.pointerType = ""; 222 instance.longPressFired = false; 223 instance.lastMoveNotification = 0; 224} 225 226function createGestureArgs(instance, e, direction, canceled) { 227 const deltaX = e.clientX - instance.startClientX; 228 const deltaY = e.clientY - instance.startClientY; 229 const distance = getDistance(deltaX, deltaY); 230 const duration = Math.max(e.timeStamp - instance.startTime, 0); 231 const axisDistance = isHorizontal(direction) ? Math.abs(deltaX) : Math.abs(deltaY); 232 const velocity = duration > 0 ? axisDistance / duration : 0; 233 234 return { 235 direction: direction, 236 startClientX: instance.startClientX, 237 startClientY: instance.startClientY, 238 clientX: e.clientX, 239 clientY: e.clientY, 240 deltaX: deltaX, 241 deltaY: deltaY, 242 distance: distance, 243 duration: duration, 244 velocity: velocity, 245 pointerType: instance.pointerType || e.pointerType || "", 246 canceled: canceled 247 }; 248} 249 250function createGestureArgsFromPoint(instance, clientX, clientY, timeStamp, direction, canceled) { 251 return createGestureArgs(instance, { 252 clientX: clientX, 253 clientY: clientY, 254 timeStamp: timeStamp, 255 pointerType: instance.pointerType 256 }, direction, canceled); 257} 258 259function isSwipe(instance, eventArgs) { 260 if (eventArgs.direction === GestureDirection.none) 261 return false; 262 263 if ((eventArgs.direction & instance.options.direction) === 0) 264 return false; 265 266 const axisDistance = isHorizontal(eventArgs.direction) ? Math.abs(eventArgs.deltaX) : Math.abs(eventArgs.deltaY); 267 const minimumVelocityDistance = Math.min(instance.options.swipeThreshold, 10); 268 269 return axisDistance >= instance.options.swipeThreshold 270 || (axisDistance >= minimumVelocityDistance && eventArgs.velocity >= instance.options.swipeVelocityThreshold); 271} 272 273function isTap(instance, eventArgs) { 274 return eventArgs.distance <= instance.options.tapMaximumDistance 275 && eventArgs.duration <= instance.options.tapMaximumDuration; 276} 277 278function startLongPressTimer(instance) { 279 clearLongPressTimer(instance); 280 281 if (!instance.options.notifyLongPressed) 282 return; 283 284 instance.longPressTimer = setTimeout(function () { 285 if (!instance.active || instance.options.disabled || !instance.dotnetAdapter) 286 return; 287 288 const deltaX = instance.lastClientX - instance.startClientX; 289 const deltaY = instance.lastClientY - instance.startClientY; 290 291 if (getDistance(deltaX, deltaY) > instance.options.longPressMoveTolerance) 292 return; 293 294 instance.longPressFired = true; 295 296 const direction = resolveDirection(deltaX, deltaY); 297 const eventArgs = createGestureArgsFromPoint(instance, instance.lastClientX, instance.lastClientY, instance.startTime + instance.options.longPressDuration, direction, false); 298 299 instance.dotnetAdapter.invokeMethodAsync("OnLongPressed", eventArgs); 300 }, instance.options.longPressDuration); 301} 302 303function clearLongPressTimer(instance) { 304 if (instance.longPressTimer) { 305 clearTimeout(instance.longPressTimer); 306 instance.longPressTimer = null; 307 } 308} 309 310function resolveDirection(deltaX, deltaY) { 311 if (deltaX === 0 && deltaY === 0) 312 return GestureDirection.none; 313 314 if (Math.abs(deltaX) >= Math.abs(deltaY)) { 315 return deltaX < 0 ? GestureDirection.left : GestureDirection.r
315ight; 316 } 317 318 return deltaY < 0 ? GestureDirection.up : GestureDirection.down; 319} 320 321function isHorizontal(direction) { 322 return direction === GestureDirection.left || direction === GestureDirection.right; 323} 324 325function getDistance(deltaX, deltaY) { 326 return Math.sqrt(deltaX * deltaX + deltaY * deltaY); 327} 328 329function isInteractiveElement(target, root) { 330 if (!target || !root || target === root || !target.closest) 331 return false; 332 333 const interactiveElement = target.closest("button, a, input, select, textarea, label, summary, [role='button'], [role='link'], [contenteditable='true'], [data-gesture-ignore]"); 334 335 return !!interactiveElement && root.contains(interactiveElement); 336} 337 338function normalizeOptions(options) { 339 options = options || {}; 340 const defaultDirection = GestureDirection.left | GestureDirection.right | GestureDirection.up | GestureDirection.down; 341 342 return { 343 disabled: options.disabled === true, 344 direction: typeof options.direction === "number" ? options.direction : defaultDirection, 345 swipeThreshold: numberOrDefault(options.swipeThreshold, 50), 346 swipeVelocityThreshold: numberOrDefault(options.swipeVelocityThreshold, 0.3), 347 tapMaximumDistance: numberOrDefault(options.tapMaximumDistance, 10), 348 tapMaximumDuration: numberOrDefault(options.tapMaximumDuration, 300), 349 longPressDuration: numberOrDefault(options.longPressDuration, 500), 350 longPressMoveTolerance: numberOrDefault(options.longPressMoveTolerance, 10), 351 moveThrottleInterval: numberOrDefault(options.moveThrottleInterval, 0), 352 touchAction: options.touchAction || GestureTouchAction.auto, 353 preventNativeDrag: options.preventNativeDrag !== false, 354 notifyGestureStarted: options.notifyGestureStarted === true, 355 notifyGestureMoved: options.notifyGestureMoved === true, 356 notifyGestureEnded: options.notifyGestureEnded === true, 357 notifySwiped: options.notifySwiped === true, 358 notifyTapped: options.notifyTapped === true, 359 notifyLongPressed: options.notifyLongPressed === true 360 }; 361} 362 363function numberOrDefault(value, defaultValue) { 364 const number = Number(value); 365 366 return Number.isFinite(number) ? number : defaultValue; 367} 368 369function applyTouchAction(instance) { 370 if (!instance.element) 371 return; 372 373 instance.element.style.touchAction = toTouchAction(instance.options.touchAction); 374} 375 376function toTouchAction(touchAction) { 377 switch (touchAction) { 378 case GestureTouchAction.none: 379 return "none"; 380 case GestureTouchAction.panX: 381 return "pan-x"; 382 case GestureTouchAction.panY: 383 return "pan-y"; 384 case GestureTouchAction.manipulation: 385 return "manipulation"; 386 default: 387 return "auto"; 388 } 389}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.