Skip to content

Commit 28691ca

Browse files
crisbetojelbourn
authored andcommitted
feat: make hammerjs optional (#2280)
* feat: make hammerjs optional Makes HammerJS and logs a warning if it's missing, instead of crashing the app. * Rename the MdHammerEvent interface. * Replace the HammerJS annotations with stripped-down alternatives. * Remove "hammerjs" from the "types" config.
1 parent d076bd3 commit 28691ca

File tree

10 files changed

+80
-24
lines changed

10 files changed

+80
-24
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@
3232
"@angular/http": "^2.2.0",
3333
"@angular/platform-browser": "^2.2.0",
3434
"core-js": "^2.4.1",
35-
"hammerjs": "^2.0.8",
3635
"rxjs": "5.0.0-beta.12",
3736
"systemjs": "0.19.38",
3837
"zone.js": "^0.6.23"
3938
},
39+
"optionalDependencies": {
40+
"hammerjs": "^2.0.8"
41+
},
4042
"devDependencies": {
4143
"@angular/compiler-cli": "^2.2.0",
4244
"@angular/platform-browser-dynamic": "^2.2.0",

src/demo-app/tsconfig.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
"@angular/material": [
2222
"../../dist/@angular/material"
2323
]
24-
},
25-
"types": [
26-
"hammerjs"
27-
]
24+
}
2825
},
2926
"angularCompilerOptions": {
3027
"genDir": "../../dist",

src/e2e-app/tsconfig.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@
2222
"@angular/material": [
2323
"../../dist/@angular/material"
2424
]
25-
},
26-
"types": [
27-
"hammerjs"
28-
]
25+
}
2926
},
3027
"angularCompilerOptions": {
3128
"genDir": "../../dist",

src/lib/core/core.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export * from './overlay/position/connected-position';
5050

5151
// Gestures
5252
export {GestureConfig} from './gestures/gesture-config';
53+
export * from './gestures/gesture-annotations';
5354

5455
// Ripple
5556
export {MdRipple, MdRippleModule} from './ripple/ripple';
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Stripped-down HammerJS annotations to be used within Material, which are necessary,
3+
* because HammerJS is an optional dependency. For the full annotations see:
4+
* https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/hammerjs
5+
*/
6+
7+
/** @docs-private */
8+
export interface HammerInput {
9+
preventDefault: () => {};
10+
deltaX: number;
11+
deltaY: number;
12+
center: { x: number; y: number; };
13+
}
14+
15+
/** @docs-private */
16+
export interface HammerStatic {
17+
new(element: HTMLElement | SVGElement, options?: any): HammerManager;
18+
19+
Pan: Recognizer;
20+
Swipe: Recognizer;
21+
Press: Recognizer;
22+
}
23+
24+
/** @docs-private */
25+
export interface Recognizer {
26+
new(options?: any): Recognizer;
27+
recognizeWith(otherRecognizer: Recognizer | string): Recognizer;
28+
}
29+
30+
/** @docs-private */
31+
export interface RecognizerStatic {
32+
new(options?: any): Recognizer;
33+
}
34+
35+
/** @docs-private */
36+
export interface HammerInstance {
37+
on(eventName: string, callback: Function): void;
38+
off(eventName: string, callback: Function): void;
39+
}
40+
41+
/** @docs-private */
42+
export interface HammerManager {
43+
add(recogniser: Recognizer | Recognizer[]): Recognizer;
44+
set(options: any): HammerManager;
45+
emit(event: string, data: any): void;
46+
off(events: string, handler?: Function): void;
47+
on(events: string, handler: Function): void;
48+
}

src/lib/core/gestures/gesture-config.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
1-
import {Injectable} from '@angular/core';
1+
import {Injectable, isDevMode} from '@angular/core';
22
import {HammerGestureConfig} from '@angular/platform-browser';
3+
import {HammerStatic, HammerInstance, Recognizer, RecognizerStatic} from './gesture-annotations';
34

45
/* Adjusts configuration of our gesture library, Hammer. */
56
@Injectable()
67
export class GestureConfig extends HammerGestureConfig {
8+
private _hammer: HammerStatic = typeof window !== 'undefined' ? (window as any).Hammer : null;
79

810
/* List of new event names to add to the gesture support list */
9-
events: string[] = [
11+
events: string[] = this._hammer ? [
1012
'longpress',
1113
'slide',
1214
'slidestart',
1315
'slideend',
1416
'slideright',
1517
'slideleft'
16-
];
18+
] : [];
19+
20+
constructor() {
21+
super();
22+
23+
if (!this._hammer && isDevMode()) {
24+
console.warn(
25+
'Could not find HammerJS. Certain Angular Material ' +
26+
'components may not work correctly.'
27+
);
28+
}
29+
}
1730

1831
/*
1932
* Builds Hammer instance manually to add custom recognizers that match the Material Design spec.
@@ -28,12 +41,12 @@ export class GestureConfig extends HammerGestureConfig {
2841
* TODO: Confirm threshold numbers with Material Design UX Team
2942
* */
3043
buildHammer(element: HTMLElement) {
31-
const mc = new Hammer(element);
44+
const mc = new this._hammer(element);
3245

3346
// Default Hammer Recognizers.
34-
let pan = new Hammer.Pan();
35-
let swipe = new Hammer.Swipe();
36-
let press = new Hammer.Press();
47+
let pan = new this._hammer.Pan();
48+
let swipe = new this._hammer.Swipe();
49+
let press = new this._hammer.Press();
3750

3851
// Notice that a HammerJS recognizer can only depend on one other recognizer once.
3952
// Otherwise the previous `recognizeWith` will be dropped.
@@ -46,12 +59,12 @@ export class GestureConfig extends HammerGestureConfig {
4659
// Add customized gestures to Hammer manager
4760
mc.add([swipe, press, pan, slide, longpress]);
4861

49-
return mc;
62+
return mc as HammerInstance;
5063
}
5164

5265
/** Creates a new recognizer, without affecting the default recognizers of HammerJS */
5366
private _createRecognizer(base: Recognizer, options: any, ...inheritances: Recognizer[]) {
54-
let recognizer = new (<RecognizerStatic> base.constructor)(options);
67+
let recognizer = new (base.constructor as RecognizerStatic)(options);
5568

5669
inheritances.push(base);
5770
inheritances.forEach(item => recognizer.recognizeWith(item));

src/lib/slide-toggle/slide-toggle.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
applyCssTransform,
2020
coerceBooleanProperty,
2121
GestureConfig,
22+
HammerInput,
2223
DefaultStyleCompatibilityModeModule,
2324
} from '../core';
2425
import {Observable} from 'rxjs/Observable';

src/lib/slider/slider.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import {NG_VALUE_ACCESSOR, ControlValueAccessor, FormsModule} from '@angular/for
1414
import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
1515
import {
1616
GestureConfig,
17+
HammerInput,
1718
coerceBooleanProperty,
1819
coerceNumberProperty,
1920
DefaultStyleCompatibilityModeModule,
2021
} from '../core';
21-
import {Input as HammerInput} from 'hammerjs';
2222
import {Dir} from '../core/rtl/dir';
2323
import {CommonModule} from '@angular/common';
2424
import {
@@ -32,7 +32,6 @@ import {
3232
DOWN_ARROW,
3333
} from '../core/keyboard/keycodes';
3434

35-
3635
/**
3736
* Visually, a 30px separation between tick marks looks best. This is very subjective but it is
3837
* the default separation we chose.

src/lib/slider/test-gesture-config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Injectable} from '@angular/core';
2-
import {GestureConfig} from '../core';
2+
import {GestureConfig, HammerManager} from '../core';
33

44
/**
55
* An extension of GestureConfig that exposes the underlying HammerManager instances.
@@ -17,7 +17,7 @@ export class TestGestureConfig extends GestureConfig {
1717
* Create a mapping of Hammer instances to element so that events can be emitted during testing.
1818
*/
1919
buildHammer(element: HTMLElement) {
20-
let mc = super.buildHammer(element);
20+
let mc = super.buildHammer(element) as HammerManager;
2121

2222
if (this.hammerInstances.get(element)) {
2323
this.hammerInstances.get(element).push(mc);

src/lib/tsconfig-srcs.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
"stripInternal": false,
1818
"typeRoots": [
1919
"../../node_modules/@types"
20-
],
21-
"types": [
2220
]
2321
},
2422
"exclude": [

0 commit comments

Comments
 (0)