UNPKG

@hugogo/angular-grid-layout-hugo

Version:

Grid Layout with draggable and resizable items for Angular

72 lines 14.7 kB
import { fromEvent, iif, merge } from 'rxjs'; import { filter } from 'rxjs/operators'; import { ktdNormalizePassiveListenerOptions } from './passive-listeners'; /** Options that can be used to bind a passive event listener. */ const passiveEventListenerOptions = ktdNormalizePassiveListenerOptions({ passive: true }); /** Options that can be used to bind an active event listener. */ const activeEventListenerOptions = ktdNormalizePassiveListenerOptions({ passive: false }); let isMobile = null; export function ktdIsMobileOrTablet() { if (isMobile != null) { return isMobile; } // Generic match pattern to identify mobile or tablet devices const isMobileDevice = /Android|webOS|BlackBerry|Windows Phone|iPad|iPhone|iPod/i.test(navigator.userAgent); // Since IOS 13 is not safe to just check for the generic solution. See: https://stackoverflow.com/questions/58019463/how-to-detect-device-name-in-safari-on-ios-13-while-it-doesnt-show-the-correct const isIOSMobileDevice = /iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); isMobile = isMobileDevice || isIOSMobileDevice; return isMobile; } export function ktdIsMouseEvent(event) { return event.clientX != null; } export function ktdIsTouchEvent(event) { return event.touches != null && event.touches.length != null; } export function ktdPointerClientX(event) { return ktdIsMouseEvent(event) ? event.clientX : event.touches[0].clientX; } export function ktdPointerClientY(event) { return ktdIsMouseEvent(event) ? event.clientY : event.touches[0].clientY; } export function ktdPointerClient(event) { return { clientX: ktdIsMouseEvent(event) ? event.clientX : event.touches[0].clientX, clientY: ktdIsMouseEvent(event) ? event.clientY : event.touches[0].clientY }; } /** * Emits when a mousedown or touchstart emits. Avoids conflicts between both events. * @param element, html element where to listen the events. * @param touchNumber number of the touch to track the event, default to the first one. */ export function ktdMouseOrTouchDown(element, touchNumber = 1) { return iif(() => ktdIsMobileOrTablet(), fromEvent(element, 'touchstart', passiveEventListenerOptions).pipe(filter((touchEvent) => touchEvent.touches.length === touchNumber)), fromEvent(element, 'mousedown', activeEventListenerOptions).pipe(filter((mouseEvent) => { /** * 0 : Left mouse button * 1 : Wheel button or middle button (if present) * 2 : Right mouse button */ return mouseEvent.button === 0; // Mouse down to be only fired if is left click }))); } /** * Emits when a 'mousemove' or a 'touchmove' event gets fired. * @param element, html element where to listen the events. * @param touchNumber number of the touch to track the event, default to the first one. */ export function ktdMouseOrTouchMove(element, touchNumber = 1) { return iif(() => ktdIsMobileOrTablet(), fromEvent(element, 'touchmove', activeEventListenerOptions).pipe(filter((touchEvent) => touchEvent.touches.length === touchNumber)), fromEvent(element, 'mousemove', activeEventListenerOptions)); } export function ktdTouchEnd(element, touchNumber = 1) { return merge(fromEvent(element, 'touchend').pipe(filter((touchEvent) => touchEvent.touches.length === touchNumber - 1)), fromEvent(element, 'touchcancel').pipe(filter((touchEvent) => touchEvent.touches.length === touchNumber - 1))); } /** * Emits when a there is a 'mouseup' or the touch ends. * @param element, html element where to listen the events. * @param touchNumber number of the touch to track the event, default to the first one. */ export function ktdMouseOrTouchEnd(element, touchNumber = 1) { return iif(() => ktdIsMobileOrTablet(), ktdTouchEnd(element, touchNumber), fromEvent(element, 'mouseup')); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9pbnRlci51dGlscy5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWdyaWQtbGF5b3V0LWh1Z28vc3JjLyIsInNvdXJjZXMiOlsibGliL3V0aWxzL3BvaW50ZXIudXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QyxPQUFPLEVBQUUsa0NBQWtDLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUV6RSxpRUFBaUU7QUFDakUsTUFBTSwyQkFBMkIsR0FBRyxrQ0FBa0MsQ0FBQyxFQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO0FBRXhGLGlFQUFpRTtBQUNqRSxNQUFNLDBCQUEwQixHQUFHLGtDQUFrQyxDQUFDLEVBQUMsT0FBTyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUM7QUFFeEYsSUFBSSxRQUFRLEdBQW1CLElBQUksQ0FBQztBQUVwQyxNQUFNLFVBQVUsbUJBQW1CO0lBRS9CLElBQUksUUFBUSxJQUFJLElBQUksRUFBRTtRQUNsQixPQUFPLFFBQVEsQ0FBQztLQUNuQjtJQUVELDZEQUE2RDtJQUM3RCxNQUFNLGNBQWMsR0FBRywwREFBMEQsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRTVHLG9NQUFvTTtJQUNwTSxNQUFNLGlCQUFpQixHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxLQUFLLFVBQVUsSUFBSSxTQUFTLENBQUMsY0FBYyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRTdJLFFBQVEsR0FBRyxjQUFjLElBQUksaUJBQWlCLENBQUM7SUFFL0MsT0FBTyxRQUFRLENBQUM7QUFDcEIsQ0FBQztBQUVE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LEtBQUssV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUN4RSxFQUNELFNBQVMsQ0FBYSxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUM5QyxNQUFNLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxLQUFLLFdBQVcsR0FBRyxDQUFDLENBQUMsQ0FDeEUsQ0FDSixDQUFDO0FBQ04sQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFdBQVcsR0FBRyxDQUFDO0lBQ3ZELE9BQU8sR0FBRyxDQUNOLEdBQUcsRUFBRSxDQUFDLG1CQUFtQixFQUFFLEVBQzNCLFdBQVcsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLEVBQ2pDLFNBQVMsQ0FBYSxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQzVDLENBQUM7QUFDTixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZnJvbUV2ZW50LCBpaWYsIG1lcmdlLCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBrdGROb3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zIH0gZnJvbSAnLi9wYXNzaXZlLWxpc3RlbmVycyc7XG5cbi8qKiBPcHRpb25zIHRoYXQgY2FuIGJlIHVzZWQgdG8gYmluZCBhIHBhc3NpdmUgZXZlbnQgbGlzdGVuZXIuICovXG5jb25zdCBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMgPSBrdGROb3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zKHtwYXNzaXZlOiB0cnVlfSk7XG5cbi8qKiBPcHRpb25zIHRoYXQgY2FuIGJlIHVzZWQgdG8gYmluZCBhbiBhY3RpdmUgZXZlbnQgbGlzdGVuZXIuICovXG5jb25zdCBhY3RpdmVFdmVudExpc3RlbmVyT3B0aW9ucyA9IGt0ZE5vcm1hbGl6ZVBhc3NpdmVMaXN0ZW5lck9wdGlvbnMoe3Bhc3NpdmU6IGZhbHNlfSk7XG5cbmxldCBpc01vYmlsZTogYm9vbGVhbiB8IG51bGwgPSBudWxsO1xuXG5leHBvcnQgZnVuY3Rpb24ga3RkSXNNb2JpbGVPclRhYmxldCgpOiBib29sZWFuIHtcblxuICAgIGlmIChpc01vYmlsZSAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBpc01vYmlsZTtcbiAgICB9XG5cbiAgICAvLyBHZW5lcmljIG1hdGNoIHBhdHRlcm4gdG8gaWRlbnRpZnkgbW9iaWxlIG9yIHRhYmxldCBkZXZpY2VzXG4gICAgY29uc3QgaXNNb2JpbGVEZXZpY2UgPSAvQW5kcm9pZHx3ZWJPU3xCbGFja0JlcnJ5fFdpbmRvd3MgUGhvbmV8aVBhZHxpUGhvbmV8aVBvZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG5cbiAgICAvLyBTaW5jZSBJT1MgMTMgaXMgbm90IHNhZmUgdG8ganVzdCBjaGVjayBmb3IgdGhlIGdlbmVyaWMgc29sdXRpb24uIFNlZTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTgwMTk0NjMvaG93LXRvLWRldGVjdC1kZXZpY2UtbmFtZS1pbi1zYWZhcmktb24taW9zLTEzLXdoaWxlLWl0LWRvZXNudC1zaG93LXRoZS1jb3JyZWN0XG4gICAgY29uc3QgaXNJT1NNb2JpbGVEZXZpY2UgPSAvaVBhZHxpUGhvbmV8aVBvZC8udGVzdChuYXZpZ2F0b3IucGxhdGZvcm0pIHx8IChuYXZpZ2F0b3IucGxhdGZvcm0gPT09ICdNYWNJbnRlbCcgJiYgbmF2aWdhdG9yLm1heFRvdWNoUG9pbnRzID4gMSk7XG5cbiAgICBpc01vYmlsZSA9IGlzTW9iaWxlRGV2aWNlIHx8IGlzSU9TTW9iaWxlRGV2aWNlO1xuXG4gICAgcmV0dXJuIGlzTW9iaWxlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24ga3RkSXNNb3VzZUV2ZW50KGV2ZW50OiBhbnkpOiBldmVudCBpcyBNb3VzZUV2ZW50IHtcbiAgICByZXR1cm4gKGV2ZW50IGFzIE1vdXNlRXZlbnQpLmNsaWVudFggIT0gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGt0ZElzVG91Y2hFdmVudChldmVudDogYW55KTogZXZlbnQgaXMgVG91Y2hFdmVudCB7XG4gICAgcmV0dXJuIChldmVudCBhcyBUb3VjaEV2ZW50KS50b3VjaGVzICE9IG51bGwgJiYgKGV2ZW50IGFzIFRvdWNoRXZlbnQpLnRvdWNoZXMubGVuZ3RoICE9IG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBrdGRQb2ludGVyQ2xpZW50WChldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpOiBudW1iZXIge1xuICAgIHJldHVybiBrdGRJc01vdXNlRXZlbnQoZXZlbnQpID8gZXZlbnQuY2xpZW50WCA6IGV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGt0ZFBvaW50ZXJDbGllbnRZKGV2ZW50OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCk6IG51bWJlciB7XG4gICAgcmV0dXJuIGt0ZElzTW91c2VFdmVudChldmVudCkgPyBldmVudC5jbGllbnRZIDogZXZlbnQudG91Y2hlc1swXS5jbGllbnRZO1xufVxuXG5leHBvcnQgZnVuY3Rpb24ga3RkUG9pbnRlckNsaWVudChldmVudDogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpOiB7Y2xpZW50WDogbnVtYmVyLCBjbGllbnRZOiBudW1iZXJ9IHtcbiAgICByZXR1cm4gIHtcbiAgICAgICAgY2xpZW50WDoga3RkSXNNb3VzZUV2ZW50KGV2ZW50KSA/IGV2ZW50LmNsaWVudFggOiBldmVudC50b3VjaGVzWzBdLmNsaWVudFgsXG4gICAgICAgIGNsaWVudFk6IGt0ZElzTW91c2VFdmVudChldmVudCkgPyBldmVudC5jbGllbnRZIDogZXZlbnQudG91Y2hlc1swXS5jbGllbnRZXG4gICAgfTtcbn1cblxuLyoqXG4gKiBFbWl0cyB3aGVuIGEgbW91c2Vkb3duIG9yIHRvdWNoc3RhcnQgZW1pdHMuIEF2b2lkcyBjb25mbGljdHMgYmV0d2VlbiBib3RoIGV2ZW50cy5cbiAqIEBwYXJhbSBlbGVtZW50LCBodG1sIGVsZW1lbnQgd2hlcmUgdG8gIGxpc3RlbiB0aGUgZXZlbnRzLlxuICogQHBhcmFtIHRvdWNoTnVtYmVyIG51bWJlciBvZiB0aGUgdG91Y2ggdG8gdHJhY2sgdGhlIGV2ZW50LCBkZWZhdWx0IHRvIHRoZSBmaXJzdCBvbmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBrdGRNb3VzZU9yVG91Y2hEb3duKGVsZW1lbnQsIHRvdWNoTnVtYmVyID0gMSk6IE9ic2VydmFibGU8TW91c2VFdmVudCB8IFRvdWNoRXZlbnQ+IHtcbiAgICByZXR1cm4gaWlmKFxuICAgICAgICAoKSA9PiBrdGRJc01vYmlsZU9yVGFibGV0KCksXG4gICAgICAgIGZyb21FdmVudDxUb3VjaEV2ZW50PihlbGVtZW50LCAndG91Y2hzdGFydCcsIHBhc3NpdmVFdmVudExpc3RlbmVyT3B0aW9ucyBhcyBBZGRFdmVudExpc3RlbmVyT3B0aW9ucykucGlwZShcbiAgICAgICAgICAgIGZpbHRlcigodG91Y2hFdmVudCkgPT4gdG91Y2hFdmVudC50b3VjaGVzLmxlbmd0aCA9PT0gdG91Y2hOdW1iZXIpXG4gICAgICAgICksXG4gICAgICAgIGZyb21FdmVudDxNb3VzZUV2ZW50PihlbGVtZW50LCAnbW91c2Vkb3duJywgYWN0aXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMgYXMgQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMpLnBpcGUoXG4gICAgICAgICAgICBmaWx0ZXIoKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiAwIDogTGVmdCBtb3VzZSBidXR0b25cbiAgICAgICAgICAgICAgICAgKiAxIDogV2hlZWwgYnV0dG9uIG9yIG1pZGRsZSBidXR0b24gKGlmIHByZXNlbnQpXG4gICAgICAgICAgICAgICAgICogMiA6IFJpZ2h0IG1vdXNlIGJ1dHRvblxuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIHJldHVybiBtb3VzZUV2ZW50LmJ1dHRvbiA9PT0gMDsgLy8gTW91c2UgZG93biB0byBiZSBvbmx5IGZpcmVkIGlmIGlzIGxlZnQgY2xpY2tcbiAgICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICApO1xufVxuXG4vKipcbiAqIEVtaXRzIHdoZW4gYSAnbW91c2Vtb3ZlJyBvciBhICd0b3VjaG1vdmUnIGV2ZW50IGdldHMgZmlyZWQuXG4gKiBAcGFyYW0gZWxlbWVudCwgaHRtbCBlbGVtZW50IHdoZXJlIHRvICBsaXN0ZW4gdGhlIGV2ZW50cy5cbiAqIEBwYXJhbSB0b3VjaE51bWJlciBudW1iZXIgb2YgdGhlIHRvdWNoIHRvIHRyYWNrIHRoZSBldmVudCwgZGVmYXVsdCB0byB0aGUgZmlyc3Qgb25lLlxuICovXG5leHBvcnQgZnVuY3Rpb24ga3RkTW91c2VPclRvdWNoTW92ZShlbGVtZW50LCB0b3VjaE51bWJlciA9IDEpOiBPYnNlcnZhYmxlPE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PiB7XG4gICAgcmV0dXJuIGlpZihcbiAgICAgICAgKCkgPT4ga3RkSXNNb2JpbGVPclRhYmxldCgpLFxuICAgICAgICBmcm9tRXZlbnQ8VG91Y2hFdmVudD4oZWxlbWVudCwgJ3RvdWNobW92ZScsIGFjdGl2ZUV2ZW50TGlzdGVuZXJPcHRpb25zIGFzIEFkZEV2ZW50TGlzdGVuZXJPcHRpb25zKS5waXBlKFxuICAgICAgICAgICAgZmlsdGVyKCh0b3VjaEV2ZW50KSA9PiB0b3VjaEV2ZW50LnRvdWNoZXMubGVuZ3RoID09PSB0b3VjaE51bWJlciksXG4gICAgICAgICksXG4gICAgICAgIGZyb21FdmVudDxNb3VzZUV2ZW50PihlbGVtZW50LCAnbW91c2Vtb3ZlJywgYWN0aXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMgYXMgQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMpXG4gICAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGt0ZFRvdWNoRW5kKGVsZW1lbnQsIHRvdWNoTnVtYmVyID0gMSk6IE9ic2VydmFibGU8VG91Y2hFdmVudD4ge1xuICAgIHJldHVybiBtZXJnZShcbiAgICAgICAgZnJvbUV2ZW50PFRvdWNoRXZlbnQ+KGVsZW1lbnQsICd0b3VjaGVuZCcpLnBpcGUoXG4gICAgICAgICAgICBmaWx0ZXIoKHRvdWNoRXZlbnQpID0+IHRvdWNoRXZlbnQudG91Y2hlcy5sZW5ndGggPT09IHRvdWNoTnVtYmVyIC0gMSlcbiAgICAgICAgKSxcbiAgICAgICAgZnJvbUV2ZW50PFRvdWNoRXZlbnQ+KGVsZW1lbnQsICd0b3VjaGNhbmNlbCcpLnBpcGUoXG4gICAgICAgICAgICBmaWx0ZXIoKHRvdWNoRXZlbnQpID0+IHRvdWNoRXZlbnQudG91Y2hlcy5sZW5ndGggPT09IHRvdWNoTnVtYmVyIC0gMSlcbiAgICAgICAgKVxuICAgICk7XG59XG5cbi8qKlxuICogRW1pdHMgd2hlbiBhIHRoZXJlIGlzIGEgJ21vdXNldXAnIG9yIHRoZSB0b3VjaCBlbmRzLlxuICogQHBhcmFtIGVsZW1lbnQsIGh0bWwgZWxlbWVudCB3aGVyZSB0byAgbGlzdGVuIHRoZSBldmVudHMuXG4gKiBAcGFyYW0gdG91Y2hOdW1iZXIgbnVtYmVyIG9mIHRoZSB0b3VjaCB0byB0cmFjayB0aGUgZXZlbnQsIGRlZmF1bHQgdG8gdGhlIGZpcnN0IG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGt0ZE1vdXNlT3JUb3VjaEVuZChlbGVtZW50LCB0b3VjaE51bWJlciA9IDEpOiBPYnNlcnZhYmxlPE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PiB7XG4gICAgcmV0dXJuIGlpZihcbiAgICAgICAgKCkgPT4ga3RkSXNNb2JpbGVPclRhYmxldCgpLFxuICAgICAgICBrdGRUb3VjaEVuZChlbGVtZW50LCB0b3VjaE51bWJlciksXG4gICAgICAgIGZyb21FdmVudDxNb3VzZUV2ZW50PihlbGVtZW50LCAnbW91c2V1cCcpLFxuICAgICk7XG59XG4iXX0=