Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plan to support Vue 3? #42

Open
sdetweil opened this issue Oct 22, 2020 · 2 comments
Open

Plan to support Vue 3? #42

sdetweil opened this issue Oct 22, 2020 · 2 comments

Comments

@sdetweil
Copy link

sdetweil commented Oct 22, 2020

Plugins for Vue 3 have changed structure

trying to use in Ionic Vue 3
get error on app.use()

S2345: Argument of type 'typeof import("/home/sam/ionic/config/node_modules/@types/vue2-hammer/index")' is not assignable to parameter of type 'Plugin_2'.
[vue-cli-service]   Property 'install' is missing in type 'typeof import("/home/sam/ionic/config/node_modules/@types/vue2-hammer/index")' but required in type '{ install: PluginInstallFunction; }'.
@lights0123
Copy link

lights0123 commented Jul 5, 2021

Ported

// @ts-nocheck

import Hammer from 'hammerjs';
import { Plugin } from 'vue';

const gestures = ['tap', 'pan', 'pinch', 'press', 'rotate', 'swipe'];
const subGestures = [
	'panstart',
	'panend',
	'panmove',
	'pancancel',
	'pinchstart',
	'pinchmove',
	'pinchend',
	'pinchcancel',
	'pinchin',
	'pinchout',
	'pressup',
	'rotatestart',
	'rotatemove',
	'rotateend',
	'rotatecancel',
];
const directions = ['up', 'down', 'left', 'right', 'horizontal', 'vertical', 'all'];

export const VueHammer: Plugin = {
	install(Vue, config = {}) {
		Vue.directive('hammer', {
			beforeMount: (el, binding) => {
				if (!el.hammer) {
					el.hammer = new Hammer.Manager(el);
				}
				const mc = el.hammer;

				// determine event type
				const event = binding.arg;
				if (!event) {
					console.warn('[vue-hammer] event type argument is required.');
				}
				el.__hammerConfig = el.__hammerConfig || {};
				el.__hammerConfig[event] = {};

				const direction = binding.modifiers;
				el.__hammerConfig[event].direction = el.__hammerConfig[event].direction || [];
				if (Object.keys(direction).length) {
					Object.keys(direction)
						.filter((keyName) => binding.modifiers[keyName])
						.forEach((keyName) => {
							const elDirectionArray = el.__hammerConfig[event].direction;
							if (elDirectionArray.indexOf(keyName) === -1) {
								elDirectionArray.push(String(keyName));
							}
						});
				}

				let recognizerType, recognizer;

				if (config.customEvents?.[event]) {
					// custom event
					const custom = config.customEvents[event];
					recognizerType = custom.type;
					recognizer = new Hammer[this.capitalize(recognizerType)](custom);
					recognizer.recognizeWith(mc.recognizers);
					mc.add(recognizer);
				} else {
					// built-in event
					recognizerType = gestures.find((gesture) => gesture === event);
					const subGesturesType = subGestures.find((gesture) => gesture === event);
					if (!recognizerType && !subGesturesType) {
						console.warn('[vue-hammer] invalid event type: ' + event);
						return;
					}
					if (
						subGesturesType &&
						el.__hammerConfig[subGesturesType].direction.length !== 0
					) {
						console.warn(
							'[vue-hammer] ' + subGesturesType + ' should not have directions'
						);
					}
					if (!recognizerType) {
						return;
					}
					if (
						recognizerType === 'tap' ||
						recognizerType === 'pinch' ||
						recognizerType === 'press' ||
						recognizerType === 'rotate'
					) {
						if (el.__hammerConfig[recognizerType].direction.length !== 0) {
							throw Error(
								'[vue-hammer] ' + recognizerType + ' should not have directions'
							);
						}
					}
					recognizer = mc.get(recognizerType);
					if (!recognizer) {
						// add recognizer
						recognizer = new Hammer[this.capitalize(recognizerType)]();
						// make sure multiple recognizers work together...
						recognizer.recognizeWith(mc.recognizers);
						mc.add(recognizer);
					}
					// apply global options
					const globalOptions = config[recognizerType];
					if (globalOptions) {
						this.guardDirections(globalOptions);
						recognizer.set(globalOptions);
					}
					// apply local options
					const localOptions = el.hammerOptions && el.hammerOptions[recognizerType];
					if (localOptions) {
						this.guardDirections(localOptions);
						recognizer.set(localOptions);
					}
				}
			},
			mounted: (el, binding) => {
				const mc = el.hammer;
				const event = binding.arg;
				const eventWithDir = subGestures.find((subGes) => subGes === event)
					? event
					: this.buildEventWithDirections(event, el.__hammerConfig[event].direction);
				if (mc.handler) {
					mc.off(eventWithDir, mc.handler);
				}
				if (typeof binding.value !== 'function') {
					mc.handler = null;
					console.warn(
						'[vue-hammer] invalid handler function for v-hammer: ' + binding.arg
					);
				} else {
					mc.on(eventWithDir, (mc.handler = binding.value));
				}
			},
			updated: (el, binding) => {
				const mc = el.hammer;
				const event = binding.arg;
				const eventWithDir = subGestures.find((subGes) => subGes === event)
					? event
					: this.buildEventWithDirections(event, el.__hammerConfig[event].direction);
				// teardown old handler
				if (mc.handler) {
					mc.off(eventWithDir, mc.handler);
				}
				if (typeof binding.value !== 'function') {
					mc.handler = null;
					console.warn(
						'[vue-hammer] invalid handler function for v-hammer: ' + binding.arg
					);
				} else {
					mc.on(eventWithDir, (mc.handler = binding.value));
				}
			},
			unmounted: (el, binding) => {
				const mc = el.hammer;
				const event = binding.arg;
				const eventWithDir = subGestures.find((subGes) => subGes === event)
					? event
					: this.buildEventWithDirections(event, el.__hammerConfig[event].direction);
				if (mc.handler) {
					el.hammer.off(eventWithDir, mc.handler);
				}
				if (!Object.keys(mc.handlers).length) {
					el.hammer.destroy();
					el.hammer = null;
				}
			},
		});
	},
	guardDirections(options) {
		const dir = options.direction;
		if (typeof dir === 'string') {
			const hammerDirection = 'DIRECTION_' + dir.toUpperCase();
			if (
				directions.indexOf(dir) > -1 &&
				Object.prototype.hasOwnProperty.call(Hammer, hammerDirection)
			) {
				options.direction = Hammer[hammerDirection];
			} else {
				console.warn('[vue-hammer] invalid direction: ' + dir);
			}
		}
	},
	buildEventWithDirections(eventName, directionArray) {
		const f = {};
		directionArray.forEach((dir) => {
			dir = dir.toLowerCase();
			if (dir === 'horizontal') {
				f.left = 1;
				f.right = 1;
			} else if (dir === 'vertical') {
				f.up = 1;
				f.down = 1;
			} else if (dir === 'all') {
				f.left = 1;
				f.right = 1;
				f.up = 1;
				f.down = 1;
			} else {
				f[dir] = 1;
			}
		});
		const _directionArray = Object.keys(f);
		if (_directionArray.length === 0) {
			return eventName;
		}
		const eventWithDirArray = _directionArray.map((dir) => {
			return eventName + dir;
		});
		return eventWithDirArray.join(' ');
	},
	capitalize(str) {
		return str.charAt(0).toUpperCase() + str.slice(1);
	},
};
app.use(VueHammer, {
	threshold: 0,
});

@sdetweil
Copy link
Author

sdetweil commented Jul 6, 2021

thx, I think I was using doubletap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants