westures-core 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 1.3.1
6
+
7
+ - Add 'contextmenu' to CANCEL_EVENTS
8
+ - Changed docs deployment strategy
9
+
3
10
  ## 1.3.0
4
11
 
5
12
  - Introduce "headless" mode, which allows westures to be run in a server environment.
@@ -0,0 +1,121 @@
1
+ # Contributing to westures-core
2
+
3
+ Thanks for contributing to westures-core. Contributions to the gesture engine,
4
+ tests, documentation, and examples are welcome.
5
+
6
+ ## Development Setup
7
+
8
+ This project uses npm and is [tested in CI](./.github/workflows/node.js.yml) across a matrix of recent Node versions.
9
+
10
+ Install dependencies with:
11
+
12
+ ```sh
13
+ npm clean-install --ignore-scripts
14
+ ```
15
+
16
+ ## Common commands
17
+
18
+ Run the same checks used by CI before opening a pull request:
19
+
20
+ ```bash
21
+ npm run build
22
+ npm run lint
23
+ npm test
24
+ npm run test:coverage
25
+ ```
26
+
27
+ Additional useful commands:
28
+
29
+ ```bash
30
+ npm run build:debug
31
+ npm run lint:fix
32
+ ```
33
+
34
+ ## Development Workflow
35
+
36
+ - Keep changes focused and update tests when behavior changes.
37
+ - Update `CHANGELOG.md` for notable user-facing, maintenance, or security changes.
38
+ - Open a pull request using the repository's pull request template.
39
+
40
+ The source is in `src/`, tests are in `test/`, and `index.js` is the package
41
+ entry point. The `dist/` directory contains build output; regenerate it with
42
+ `npm run build` rather than editing it directly.
43
+
44
+ Follow the existing JavaScript style. ESLint enforces the project conventions,
45
+ including two-space indentation, single quotes, semicolons, and trailing commas
46
+ in multiline constructs.
47
+
48
+ ## Pull Requests
49
+
50
+ Before opening a pull request, run the build, linter, and relevant tests. Give
51
+ the pull request a clear description, explain any behavioral changes, and use
52
+ the provided pull request template to identify its type. Keep unrelated
53
+ formatting or refactoring changes out of the pull request.
54
+
55
+ For bugs, include a regression test when practical. For user-facing API or
56
+ behavior changes, update the README and JSDoc documentation as appropriate.
57
+
58
+ ## Publishing Documentation
59
+
60
+ Published documentation is generated with `npm run docs` and deployed from the
61
+ generated `docs/` directory by the
62
+ [documentation deployment workflow](./.github/workflows/deploy-documentation.yaml).
63
+
64
+ To publish the current `deploy-docs` branch, push your changes to that branch.
65
+ For a one-off deployment from another branch, run the **Build and Deploy**
66
+ workflow manually in GitHub Actions and select the branch to deploy. The
67
+ workflow installs dependencies, regenerates the documentation, and publishes
68
+ the resulting `docs/` directory, so do not commit generated documentation just
69
+ to deploy it.
70
+
71
+ ## Reporting Issues
72
+
73
+ When reporting a bug, include the Node.js version, browser and version when
74
+ relevant, a minimal reproduction, expected behavior, and actual behavior.
75
+
76
+ ## License
77
+
78
+ By contributing, you agree that your contributions are licensed under the
79
+ [MIT License](LICENSE).
80
+
81
+ ## Release process
82
+
83
+ For a package release, use the following workflow so you publish from the same
84
+ source commit you tag (with build artifacts generated locally), while only
85
+ pushing the tag after `npm publish` succeeds.
86
+
87
+ 1. Create a release preparation branch from `main`.
88
+ 2. Update `package.json`, `package-lock.json`, and `CHANGELOG.md` for the new version.
89
+ 3. Commit the release preparation changes and open a pull request.
90
+ 4. Merge the pull request into `main`.
91
+ 5. Check out the merged `main` commit locally.
92
+ 6. Verify the working tree is clean.
93
+ 7. Create the release tag locally for that commit, but do not push it yet.
94
+ 8. Check what will be published with `npm pack --dry-run`.
95
+ 9. Sanity-check the built bundle in `dist/index.js`.
96
+ 10. Publish the package to npm from the tagged commit.
97
+ 11. Push the tag.
98
+ 12. Create the GitHub release from the pushed tag.
99
+
100
+ Example commands for `1.3.1`:
101
+
102
+ ```bash
103
+ git switch --create release/1.3.1
104
+ git add package.json package-lock.json CHANGELOG.md
105
+ git commit --message "Prepare for 1.3.1 release"
106
+ gh pr create
107
+ # merge the PR, then sync your local main to the merged commit
108
+ git switch main
109
+ git pull --ff-only origin main
110
+ git status --short # must produce no output
111
+ git tag --annotate v1.3.1 --message "Release 1.3.1"
112
+ npm pack --dry-run # also builds, via 'prepare' script
113
+ ls -lh dist/index.js
114
+ npm publish
115
+ git push origin v1.3.1
116
+ gh release create v1.3.1 --title "v1.3.1"
117
+ ```
118
+
119
+ If you want GitHub release notes to match the changelog closely, paste the
120
+ `1.3.1` section of `CHANGELOG.md` into the release notes when creating the
121
+ release.
package/README.md CHANGED
@@ -4,11 +4,9 @@
4
4
  [![Coverage Status](https://coveralls.io/repos/github/mvanderkamp/westures-core/badge.svg?branch=main)](https://coveralls.io/github/mvanderkamp/westures-core?branch=main)
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/a5f4a4745352d6e2520c/maintainability)](https://codeclimate.com/github/mvanderkamp/westures-core/maintainability)
6
6
 
7
- Westures is a robust n-pointer multitouch gesture detection library for
8
- JavaScript. This means that each gesture is be capable of working seamlessly as
9
- input points are added and removed, with no limit on the number of input points,
10
- and with each input point contributing to the gesture. It is also capable of
11
- working across a wide range of devices.
7
+ Westures is an n-pointer gesture detection library for JavaScript. Gestures can
8
+ continue as input points are added and removed, with each active input point
9
+ available to the gesture.
12
10
 
13
11
  This module contains the core functionality of the Westures gesture library for
14
12
  JavaScript. It is intended for use as a lighter-weight module to use if you do
@@ -18,13 +16,10 @@ https://mvanderkamp.github.io/westures/) module.
18
16
  Visit this page for an example of the system in action: [Westures Example](
19
17
  https://mvanderkamp.github.io/westures-example/).
20
18
 
21
- Westures aims to achieve its goals without using any dependencies, yet maintain
22
- usability across the main modern browsers. Transpilation may be necessary for
23
- this last point to be achieved, as the library is written using many of the
24
- newer features of the JavaScript language. A transpiled bundle is provided, but
25
- the browser target list is arbitrary and likely includes some bloat. In most
26
- cases you will be better off performing bundling, transpilation, and
27
- minification yourself.
19
+ Westures has no runtime dependencies. It uses Pointer Events when available and
20
+ otherwise listens to mouse and touch events. The package's CommonJS entry point
21
+ is a bundled build; applications that target older browsers may need to
22
+ transpile it as part of their own build pipeline.
28
23
 
29
24
  Westures is a fork of [ZingTouch](https://github.com/zingchart/zingtouch).
30
25
 
@@ -40,6 +35,10 @@ const region = new wes.Region();
40
35
 
41
36
  // Define a Gesture subclass
42
37
  class Follow extends wes.Gesture {
38
+ constructor(element, handler, options) {
39
+ super('follow', element, handler, options);
40
+ }
41
+
43
42
  move(state) {
44
43
  return state.centroid; // Reports the {x, y} of the average input position
45
44
  }
@@ -62,11 +61,13 @@ region.addGesture(follow);
62
61
 
63
62
  - [Features](#features)
64
63
  - [Overview](#overview)
64
+ - [Installation](#installation)
65
65
  - [Basic Usage](#basic-usage)
66
66
  - [Implementing Custom Gestures](#implementing-custom-gestures)
67
67
  - [Nomenclature and Origins](#nomenclature-and-origins)
68
68
  - [Changes](#changes)
69
69
  - [Issues](#issues)
70
+ - [Contributing](#contributing)
70
71
  - [Links](#links)
71
72
 
72
73
  ## Features
@@ -98,12 +99,26 @@ Region | Listen for user input events and respond appropriately
98
99
  Smoothable | Datatype which provides inertial smoothing capabilities
99
100
  State | Track inputs within a Region
100
101
 
101
- Additionally, two support files are defined:
102
+ The package also exports its constants and utility functions, including
103
+ `PHASES`, `STATE_KEYS`, `angularDifference`, and `setFilter`.
104
+
105
+ ## Installation
106
+
107
+ ```sh
108
+ npm install westures-core
109
+ ```
110
+
111
+ The package uses CommonJS:
102
112
 
103
- Name | Description
104
- --------- | -----------
105
- constants | Constant values used throughout the engine
106
- utils | Helpful utility functions
113
+ ```javascript
114
+ const wes = require('westures-core');
115
+ ```
116
+
117
+ `Region` requires a browser environment by default. For server-side or test
118
+ use, create it in headless mode and provide events directly to
119
+ `arbitrate(event)`, `cancel(event)`, and `handleKeyboardEvent(event)`. Events
120
+ passed to a headless region must include a `target` so the region can select
121
+ the gesture to evaluate.
107
122
 
108
123
  ## Basic Usage
109
124
 
@@ -112,12 +127,6 @@ utils | Helpful utility functions
112
127
  - [Instantiating a Gesture](#instantiating-a-gesture)
113
128
  - [Adding a Gesture to a Region](#adding-a-gesture-to-a-region)
114
129
 
115
- ### Importing the module
116
-
117
- ```javascript
118
- const wes = require('westures-core');
119
- ```
120
-
121
130
  ### Declaring a Region
122
131
 
123
132
  First, decide what region should listen for events. This could be the
@@ -150,6 +159,10 @@ input points. Note that the returned value must be an Object!
150
159
  ```javascript
151
160
  // Define a Gesture subclass
152
161
  class Follow extends wes.Gesture {
162
+ constructor(element, handler, options) {
163
+ super('follow', element, handler, options);
164
+ }
165
+
153
166
  move(state) {
154
167
  return state.centroid;
155
168
  }
@@ -173,7 +186,7 @@ const element = document.querySelector('#follow');
173
186
  ```
174
187
 
175
188
  And we also need a handler. This function will be called whenever a gesture hook
176
- returns non-null data. For Follow, this is just the move phase, but the handler
189
+ returns an object. For Follow, this is just the move phase, but the handler
177
190
  doesn't need to know that. The data returned by the hook will be available
178
191
  inside the handler.
179
192
 
@@ -227,18 +240,19 @@ const { Gesture } = require('westures-core');
227
240
  const TIMEOUT = 100;
228
241
 
229
242
  class Tap extends Gesture {
230
- constructor() {
231
- super('tap');
243
+ constructor(element, handler, options) {
244
+ super('tap', element, handler, options);
232
245
  this.startTime = null;
233
246
  }
234
247
 
235
- start(state) {
248
+ start() {
236
249
  this.startTime = Date.now();
237
250
  }
238
251
 
239
252
  end(state) {
240
253
  if (Date.now() - this.startTime <= TIMEOUT) {
241
- return state.getInputsInPhase('end')[0].current.point;
254
+ const point = state.getInputsInPhase('end')[0].current.point;
255
+ return { centroid: point, ...point };
242
256
  }
243
257
  return null;
244
258
  }
@@ -249,7 +263,7 @@ There are problems with this example, and it should probably not be used as an
249
263
  actual Tap gesture, it is merely to illustrate the basic idea.
250
264
 
251
265
  The default hooks for all Gestures simply return null. Data will only be
252
- forwarded to bound handlers when a non-null value is returned by a hook.
266
+ forwarded to bound handlers when an object is returned by a hook.
253
267
  Returned values should be packed inside an object. For example, instead of just
254
268
  `return 42;`, a custom hook should do `return { value: 42 };`
255
269
 
@@ -269,7 +283,7 @@ called. Those properties are:
269
283
 
270
284
  Name | Type | Value
271
285
  -------- | -------- | -----
272
- centroid | Point2D | The centroid of the input points.
286
+ centroid | Point2D \| null | The centroid of the active input points.
273
287
  event | Event | The input event which caused the gesture to be recognized
274
288
  phase | String | `'start'`, `'move'`, `'end'`, or `'cancel'`
275
289
  type | String | The name of the gesture as specified by its designer.
@@ -279,9 +293,21 @@ If data properties returned by a hook have a name collision with one of these
279
293
  properties, the value from the hook gets precedent and the default is
280
294
  overwritten.
281
295
 
296
+ ### Ending Inputs
297
+
298
+ `State.active`, `State.activePoints`, and the default `centroid` represent only
299
+ active inputs. During an `end` hook, this means that inputs ending in the
300
+ current event are excluded; when the final input ends, the default `centroid`
301
+ is `null`.
302
+
303
+ Gestures based on released inputs should read them with
304
+ `state.getInputsInPhase('end')`, retain any data they need, and return their
305
+ own result. A tap gesture, for example, can compute its own centroid from the
306
+ ending inputs and return it as `centroid`, as in the example above.
307
+
282
308
  ## Nomenclature and Origins
283
309
 
284
- In my last year of univerisity, I was working on an API for building
310
+ In my last year of university, I was working on an API for building
285
311
  multi-device interfaces called "WAMS" (Workspaces Across Multiple Surfaces),
286
312
  which included the goal of supporting multi-device gestures.
287
313
 
@@ -296,13 +322,18 @@ The name "westures" is a mash-up of "WAMS" and "gestures".
296
322
  ## Changes
297
323
 
298
324
  See the [changelog](
299
- https://github.com/mvanderkamp/westures-core/blob/master/CHANGELOG.md) for the
325
+ https://github.com/mvanderkamp/westures-core/blob/main/CHANGELOG.md) for the
300
326
  most recent updates.
301
327
 
302
328
  ## Issues
303
329
 
304
330
  If you find any issues, please let me know!
305
331
 
332
+ ## Contributing
333
+
334
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the development workflow and pull
335
+ request guidelines.
336
+
306
337
  ## Links
307
338
 
308
339
  ### westures
@@ -316,4 +347,3 @@ If you find any issues, please let me know!
316
347
  - [npm](https://www.npmjs.com/package/westures-core)
317
348
  - [github](https://github.com/mvanderkamp/westures-core)
318
349
  - [documentation](https://mvanderkamp.github.io/westures-core/)
319
-
package/dist/index.js CHANGED
@@ -3,9 +3,9 @@
3
3
  * and routines used by the package. Use responsibly.
4
4
  *
5
5
  * @namespace westures-core
6
- */ "use strict";
6
+ */ 'use strict';
7
7
  var $de0d6a332419bf3c$exports = {};
8
- "use strict";
8
+ 'use strict';
9
9
  let $de0d6a332419bf3c$var$g_id = 0;
10
10
  /**
11
11
  * The Gesture class that all gestures inherit from. A custom gesture class will
@@ -33,7 +33,7 @@ let $de0d6a332419bf3c$var$g_id = 0;
33
33
  * pointers that may be active for the gesture to be recognized. Uses <=.
34
34
  */ class $de0d6a332419bf3c$var$Gesture {
35
35
  constructor(type, element, handler, options = {}){
36
- if (typeof type !== "string") throw new TypeError("Gestures require a string type / name");
36
+ if (typeof type !== 'string') throw new TypeError('Gestures require a string type / name');
37
37
  /**
38
38
  * The name of the gesture. (e.g. 'pan' or 'tap' or 'pinch').
39
39
  *
@@ -76,7 +76,7 @@ let $de0d6a332419bf3c$var$g_id = 0;
76
76
  */ isEnabled(state) {
77
77
  const count = state.active.length;
78
78
  const event = state.event;
79
- const { enableKeys: enableKeys , disableKeys: disableKeys , minInputs: minInputs , maxInputs: maxInputs } = this.options;
79
+ const { enableKeys: enableKeys, disableKeys: disableKeys, minInputs: minInputs, maxInputs: maxInputs } = this.options;
80
80
  return minInputs <= count && maxInputs >= count && (enableKeys.length === 0 || enableKeys.some((k)=>event[k])) && !disableKeys.some((k)=>event[k]);
81
81
  }
82
82
  /**
@@ -166,11 +166,11 @@ $de0d6a332419bf3c$exports = $de0d6a332419bf3c$var$Gesture;
166
166
 
167
167
 
168
168
  var $e2125e2e71e37a0c$exports = {};
169
- "use strict";
169
+ 'use strict';
170
170
  var $0ca7bfe1c074e8ca$exports = {};
171
- "use strict";
171
+ 'use strict';
172
172
  var $6c3676f10a43b740$exports = {};
173
- "use strict";
173
+ 'use strict';
174
174
  /**
175
175
  * The Point2D class stores and operates on 2-dimensional points, represented as
176
176
  * x and y coordinates.
@@ -306,17 +306,18 @@ $6c3676f10a43b740$exports = $6c3676f10a43b740$var$Point2D;
306
306
 
307
307
 
308
308
  var $be6f0e84320366a7$exports = {};
309
- "use strict";
309
+ 'use strict';
310
310
  /**
311
311
  * List of events that trigger the cancel phase.
312
312
  *
313
313
  * @memberof westures-core
314
314
  * @type {string[]}
315
315
  */ const $be6f0e84320366a7$var$CANCEL_EVENTS = [
316
- "blur",
317
- "pointercancel",
318
- "touchcancel",
319
- "mouseleave"
316
+ 'blur',
317
+ 'contextmenu',
318
+ 'pointercancel',
319
+ 'touchcancel',
320
+ 'mouseleave'
320
321
  ];
321
322
  /**
322
323
  * List of keyboard events that trigger a restart.
@@ -324,8 +325,8 @@ var $be6f0e84320366a7$exports = {};
324
325
  * @memberof westures-core
325
326
  * @type {string[]}
326
327
  */ const $be6f0e84320366a7$var$KEYBOARD_EVENTS = [
327
- "keydown",
328
- "keyup"
328
+ 'keydown',
329
+ 'keyup'
329
330
  ];
330
331
  /**
331
332
  * List of mouse events to listen to.
@@ -333,9 +334,9 @@ var $be6f0e84320366a7$exports = {};
333
334
  * @memberof westures-core
334
335
  * @type {string[]}
335
336
  */ const $be6f0e84320366a7$var$MOUSE_EVENTS = [
336
- "mousedown",
337
- "mousemove",
338
- "mouseup"
337
+ 'mousedown',
338
+ 'mousemove',
339
+ 'mouseup'
339
340
  ];
340
341
  /**
341
342
  * List of pointer events to listen to.
@@ -343,9 +344,9 @@ var $be6f0e84320366a7$exports = {};
343
344
  * @memberof westures-core
344
345
  * @type {string[]}
345
346
  */ const $be6f0e84320366a7$var$POINTER_EVENTS = [
346
- "pointerdown",
347
- "pointermove",
348
- "pointerup"
347
+ 'pointerdown',
348
+ 'pointermove',
349
+ 'pointerup'
349
350
  ];
350
351
  /**
351
352
  * List of touch events to listen to.
@@ -353,9 +354,9 @@ var $be6f0e84320366a7$exports = {};
353
354
  * @memberof westures-core
354
355
  * @type {string[]}
355
356
  */ const $be6f0e84320366a7$var$TOUCH_EVENTS = [
356
- "touchend",
357
- "touchmove",
358
- "touchstart"
357
+ 'touchend',
358
+ 'touchmove',
359
+ 'touchstart'
359
360
  ];
360
361
  /**
361
362
  * List of potentially state-modifying keys.
@@ -364,10 +365,10 @@ var $be6f0e84320366a7$exports = {};
364
365
  * @memberof westures-core
365
366
  * @type {string[]}
366
367
  */ const $be6f0e84320366a7$var$STATE_KEYS = [
367
- "altKey",
368
- "ctrlKey",
369
- "metaKey",
370
- "shiftKey"
368
+ 'altKey',
369
+ 'ctrlKey',
370
+ 'metaKey',
371
+ 'shiftKey'
371
372
  ];
372
373
  /**
373
374
  * List of the 'key' values on KeyboardEvent objects of the potentially
@@ -376,35 +377,35 @@ var $be6f0e84320366a7$exports = {};
376
377
  * @memberof westures-core
377
378
  * @type {string[]}
378
379
  */ const $be6f0e84320366a7$var$STATE_KEY_STRINGS = [
379
- "Alt",
380
- "Control",
381
- "Meta",
382
- "Shift"
380
+ 'Alt',
381
+ 'Control',
382
+ 'Meta',
383
+ 'Shift'
383
384
  ];
384
385
  /**
385
386
  * The cancel phase.
386
387
  *
387
388
  * @memberof westures-core
388
389
  * @type {string}
389
- */ const $be6f0e84320366a7$var$CANCEL = "cancel";
390
+ */ const $be6f0e84320366a7$var$CANCEL = 'cancel';
390
391
  /**
391
392
  * The end phase.
392
393
  *
393
394
  * @memberof westures-core
394
395
  * @type {string}
395
- */ const $be6f0e84320366a7$var$END = "end";
396
+ */ const $be6f0e84320366a7$var$END = 'end';
396
397
  /**
397
398
  * The move phase.
398
399
  *
399
400
  * @memberof westures-core
400
401
  * @type {string}
401
- */ const $be6f0e84320366a7$var$MOVE = "move";
402
+ */ const $be6f0e84320366a7$var$MOVE = 'move';
402
403
  /**
403
404
  * The start phase.
404
405
  *
405
406
  * @memberof westures-core
406
407
  * @type {string}
407
- */ const $be6f0e84320366a7$var$START = "start";
408
+ */ const $be6f0e84320366a7$var$START = 'start';
408
409
  /**
409
410
  * The recognized phases.
410
411
  *
@@ -477,7 +478,7 @@ var $0ca7bfe1c074e8ca$require$PHASE = $be6f0e84320366a7$exports.PHASE;
477
478
  * @param {number} identifier - The index of touch if applicable
478
479
  */ class $0ca7bfe1c074e8ca$var$PointerData {
479
480
  constructor(event, identifier){
480
- const { clientX: clientX , clientY: clientY } = $0ca7bfe1c074e8ca$var$getEventObject(event, identifier);
481
+ const { clientX: clientX, clientY: clientY } = $0ca7bfe1c074e8ca$var$getEventObject(event, identifier);
481
482
  /**
482
483
  * The original event object.
483
484
  *
@@ -506,7 +507,7 @@ $0ca7bfe1c074e8ca$exports = $0ca7bfe1c074e8ca$var$PointerData;
506
507
 
507
508
 
508
509
  var $4559ecf940edc78d$exports = {};
509
- "use strict";
510
+ 'use strict';
510
511
  const $4559ecf940edc78d$var$PI_2 = 2 * Math.PI;
511
512
  const $4559ecf940edc78d$var$PI_NVE = -Math.PI;
512
513
  /**
@@ -534,7 +535,7 @@ const $4559ecf940edc78d$var$PI_NVE = -Math.PI;
534
535
  *
535
536
  * @return {Element[]} The elements along the composed path of the event.
536
537
  */ function $4559ecf940edc78d$var$getPropagationPath(event) {
537
- if (typeof event.composedPath === "function") return event.composedPath();
538
+ if (typeof event.composedPath === 'function') return event.composedPath();
538
539
  const path = [];
539
540
  for(let node = event.target; node !== document; node = node.parentNode)path.push(node);
540
541
  path.push(document);
@@ -671,9 +672,9 @@ $e2125e2e71e37a0c$exports = $e2125e2e71e37a0c$var$Input;
671
672
 
672
673
 
673
674
  var $b66a0f22c18e3e3d$exports = {};
674
- "use strict";
675
+ 'use strict';
675
676
  var $639be6fb478a6d5a$exports = {};
676
- "use strict";
677
+ 'use strict';
677
678
 
678
679
  var $639be6fb478a6d5a$require$CANCEL = $be6f0e84320366a7$exports.CANCEL;
679
680
  var $639be6fb478a6d5a$require$END = $be6f0e84320366a7$exports.END;
@@ -686,7 +687,7 @@ var $639be6fb478a6d5a$require$TOUCH_EVENTS = $be6f0e84320366a7$exports.TOUCH_EVE
686
687
 
687
688
 
688
689
  const $639be6fb478a6d5a$var$symbols = {
689
- inputs: Symbol.for("inputs")
690
+ inputs: Symbol.for('inputs')
690
691
  };
691
692
  /**
692
693
  * Keeps track of currently active and ending input points on the interactive
@@ -734,10 +735,11 @@ const $639be6fb478a6d5a$var$symbols = {
734
735
  * @type {westures-core.Point2D[]}
735
736
  */ this.activePoints = [];
736
737
  /**
737
- * The centroid of the currently active points.
738
+ * The centroid of the currently active points, or null when there are no
739
+ * active inputs (such as during the final end event).
738
740
  *
739
- * @type {westures-core.Point2D}
740
- */ this.centroid = {};
741
+ * @type {?westures-core.Point2D}
742
+ */ this.centroid = null;
741
743
  /**
742
744
  * The latest event that the state processed.
743
745
  *
@@ -748,7 +750,7 @@ const $639be6fb478a6d5a$var$symbols = {
748
750
  * Deletes all inputs that are in the 'end' phase.
749
751
  */ clearEndedInputs() {
750
752
  this[$639be6fb478a6d5a$var$symbols.inputs].forEach((v, k)=>{
751
- if (v.phase === "end") this[$639be6fb478a6d5a$var$symbols.inputs].delete(k);
753
+ if (v.phase === 'end') this[$639be6fb478a6d5a$var$symbols.inputs].delete(k);
752
754
  });
753
755
  }
754
756
  /**
@@ -825,7 +827,7 @@ const $639be6fb478a6d5a$var$symbols = {
825
827
  * @param {Event} event - Event with which to update the convenience fields.
826
828
  */ updateFields(event) {
827
829
  this.inputs = Array.from(this[$639be6fb478a6d5a$var$symbols.inputs].values());
828
- this.active = this.getInputsNotInPhase("end");
830
+ this.active = this.getInputsNotInPhase('end');
829
831
  this.activePoints = this.active.map((i)=>i.current.point);
830
832
  this.centroid = $6c3676f10a43b740$exports.centroid(this.activePoints);
831
833
  this.event = event;
@@ -940,9 +942,7 @@ var $b66a0f22c18e3e3d$require$setFilter = $4559ecf940edc78d$exports.setFilter;
940
942
  * https://www.html5rocks.com/en/mobile/touchandmouse/
941
943
  * https://developer.mozilla.org/en-US/docs/Web/API/Touch_events
942
944
  * https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events
943
- */ let eventNames = [];
944
- if (this.options.preferPointer && window.PointerEvent) eventNames = $b66a0f22c18e3e3d$require$POINTER_EVENTS;
945
- else eventNames = $b66a0f22c18e3e3d$require$MOUSE_EVENTS.concat($b66a0f22c18e3e3d$require$TOUCH_EVENTS);
945
+ */ const eventNames = this.options.preferPointer && window.PointerEvent ? $b66a0f22c18e3e3d$require$POINTER_EVENTS : $b66a0f22c18e3e3d$require$MOUSE_EVENTS.concat($b66a0f22c18e3e3d$require$TOUCH_EVENTS);
946
946
  // Bind detected browser events to the region element.
947
947
  const arbitrate = this.arbitrate.bind(this);
948
948
  eventNames.forEach((eventName)=>{
@@ -968,7 +968,7 @@ var $b66a0f22c18e3e3d$require$setFilter = $4559ecf940edc78d$exports.setFilter;
968
968
  * @private
969
969
  * @param {Event} event - The event emitted from the window object.
970
970
  */ cancel(event) {
971
- if (this.options.preventDefault && typeof event.preventDefault === "function") event.preventDefault();
971
+ if (this.options.preventDefault && typeof event.preventDefault === 'function') event.preventDefault();
972
972
  this.state.inputs.forEach((input)=>{
973
973
  input.update(event);
974
974
  });
@@ -1060,7 +1060,7 @@ var $b66a0f22c18e3e3d$require$setFilter = $4559ecf940edc78d$exports.setFilter;
1060
1060
  this.state.updateAllInputs(event);
1061
1061
  this.updateActiveGestures(event, isInitial);
1062
1062
  if (this.activeGestures.size > 0) {
1063
- if (this.options.preventDefault && typeof event.preventDefault === "function") event.preventDefault();
1063
+ if (this.options.preventDefault && typeof event.preventDefault === 'function') event.preventDefault();
1064
1064
  this.activeGestures.forEach((gesture)=>{
1065
1065
  gesture.evaluateHook($b66a0f22c18e3e3d$require$PHASE[event.type], this.state);
1066
1066
  });
@@ -1106,16 +1106,16 @@ $b66a0f22c18e3e3d$var$Region.DEFAULTS = {
1106
1106
  capture: false,
1107
1107
  preferPointer: true,
1108
1108
  preventDefault: true,
1109
- touchAction: "none",
1109
+ touchAction: 'none',
1110
1110
  headless: false
1111
1111
  };
1112
1112
  $b66a0f22c18e3e3d$exports = $b66a0f22c18e3e3d$var$Region;
1113
1113
 
1114
1114
 
1115
1115
  var $01c3d7b128023e4f$exports = {};
1116
- "use strict";
1117
- const $01c3d7b128023e4f$var$cascade = Symbol("cascade");
1118
- const $01c3d7b128023e4f$var$smooth = Symbol("smooth");
1116
+ 'use strict';
1117
+ const $01c3d7b128023e4f$var$cascade = Symbol('cascade');
1118
+ const $01c3d7b128023e4f$var$smooth = Symbol('smooth');
1119
1119
  /**
1120
1120
  * Determines whether to apply smoothing. Smoothing is on by default but turned
1121
1121
  * off if either:<br>
@@ -1133,7 +1133,7 @@ const $01c3d7b128023e4f$var$smooth = Symbol("smooth");
1133
1133
  * @returns {boolean} Whether to apply smoothing.
1134
1134
  */ function $01c3d7b128023e4f$var$smoothingIsApplicable(isRequested) {
1135
1135
  if (isRequested) try {
1136
- return window.matchMedia("(pointer: coarse)").matches;
1136
+ return window.matchMedia('(pointer: coarse)').matches;
1137
1137
  } catch (e) {
1138
1138
  return true;
1139
1139
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","sources":["index.js","src/Gesture.js","src/Input.js","src/PointerData.js","src/Point2D.js","src/constants.js","src/utils.js","src/Region.js","src/State.js","src/Smoothable.js"],"sourcesContent":["/**\n * The global API interface for westures-core. Exposes all classes, constants,\n * and routines used by the package. Use responsibly.\n *\n * @namespace westures-core\n */\n\n'use strict';\n\nconst Gesture = require('./src/Gesture.js');\nconst Input = require('./src/Input.js');\nconst Point2D = require('./src/Point2D.js');\nconst PointerData = require('./src/PointerData.js');\nconst Region = require('./src/Region.js');\nconst Smoothable = require('./src/Smoothable.js');\nconst State = require('./src/State.js');\nconst constants = require('./src/constants.js');\nconst utils = require('./src/utils.js');\n\nmodule.exports = {\n Gesture,\n Input,\n Point2D,\n PointerData,\n Region,\n Smoothable,\n State,\n ...constants,\n ...utils,\n};\n\n","'use strict';\n\nlet g_id = 0;\n\n/**\n * The Gesture class that all gestures inherit from. A custom gesture class will\n * need to override some or all of the four phase \"hooks\": start, move, end, and\n * cancel.\n *\n * @memberof westures-core\n *\n * @param {string} type - The name of the gesture.\n * @param {Element} element - The element to which to associate the gesture.\n * @param {Function} handler - The function handler to execute when a gesture\n * is recognized on the associated element.\n * @param {object} [options] - Generic gesture options\n * @param {westures-core.STATE_KEYS[]} [options.enableKeys=[]] - List of keys\n * which will enable the gesture. The gesture will not be recognized unless one\n * of these keys is pressed while the interaction occurs. If not specified or an\n * empty list, the gesture is treated as though the enable key is always down.\n * @param {westures-core.STATE_KEYS[]} [options.disableKeys=[]] - List of keys\n * which will disable the gesture. The gesture will not be recognized if one of\n * these keys is pressed while the interaction occurs. If not specified or an\n * empty list, the gesture is treated as though the disable key is never down.\n * @param {number} [options.minInputs=1] - The minimum number of pointers that\n * must be active for the gesture to be recognized. Uses >=.\n * @param {number} [options.maxInputs=Number.MAX_VALUE] - The maximum number of\n * pointers that may be active for the gesture to be recognized. Uses <=.\n */\nclass Gesture {\n constructor(type, element, handler, options = {}) {\n if (typeof type !== 'string') {\n throw new TypeError('Gestures require a string type / name');\n }\n\n /**\n * The name of the gesture. (e.g. 'pan' or 'tap' or 'pinch').\n *\n * @type {string}\n */\n this.type = type;\n\n /**\n * The unique identifier for each gesture. This allows for distinctions\n * across instances of Gestures that are created on the fly (e.g.\n * gesture-tap-1, gesture-tap-2).\n *\n * @type {string}\n */\n this.id = `gesture-${this.type}-${g_id++}`;\n\n /**\n * The element to which to associate the gesture.\n *\n * @type {Element}\n */\n this.element = element;\n\n /**\n * The function handler to execute when the gesture is recognized on the\n * associated element.\n *\n * @type {Function}\n */\n this.handler = handler;\n\n /**\n * The options. Can usually be adjusted live, though be careful doing this.\n *\n * @type {object}\n */\n this.options = { ...Gesture.DEFAULTS, ...options };\n }\n\n /**\n * Determines whether this gesture is enabled.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {boolean} true if enabled, false otherwise.\n */\n isEnabled(state) {\n const count = state.active.length;\n const event = state.event;\n const { enableKeys, disableKeys, minInputs, maxInputs } = this.options;\n\n return (minInputs <= count) && (maxInputs >= count) &&\n (enableKeys.length === 0 || enableKeys.some(k => event[k])) &&\n !disableKeys.some(k => event[k]);\n }\n\n /**\n * Event hook for the start phase of a gesture.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n start() {\n return null;\n }\n\n /**\n * Event hook for the move phase of a gesture.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n move() {\n return null;\n }\n\n /**\n * Event hook for the end phase of a gesture.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n end() {\n return null;\n }\n\n /**\n * Event hook for when an input is cancelled.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n cancel() {\n return null;\n }\n\n /**\n * Evalutes the given gesture hook, and dispatches any data that is produced\n * by calling [recognize]{@link westures-core.Gesture#recognize}.\n *\n * @param {string} hook - Must be one of 'start', 'move', 'end', or 'cancel'.\n * @param {westures-core.State} state - The current State instance.\n */\n evaluateHook(hook, state) {\n const data = this[hook](state);\n if (data) {\n this.recognize(hook, state, data);\n }\n }\n\n /**\n * Recognize a Gesture by calling the handler. Standardizes the way the\n * handler is called so that classes extending Gesture can circumvent the\n * evaluateHook approach but still provide results that have a common format.\n *\n * Note that the properties in the \"data\" object will receive priority when\n * constructing the results. This can be used to override standard results\n * such as the phase or the centroid.\n *\n * @param {string} hook - Must be one of 'start', 'move', 'end', or 'cancel'.\n * @param {westures-core.State} state - current input state.\n * @param {Object} data - Results data specific to the recognized gesture.\n */\n recognize(hook, state, data) {\n this.handler({\n centroid: state.centroid,\n event: state.event,\n phase: hook,\n type: this.type,\n target: this.element,\n ...data,\n });\n }\n}\n\nGesture.DEFAULTS = {\n enableKeys: [],\n disableKeys: [],\n minInputs: 1,\n maxInputs: Number.MAX_VALUE,\n};\n\nmodule.exports = Gesture;\n\n","'use strict';\n\nconst PointerData = require('./PointerData.js');\nconst { getPropagationPath } = require('./utils.js');\n\n/**\n * Tracks a single input and contains information about the current, previous,\n * and initial events.\n *\n * @memberof westures-core\n *\n * @param {(PointerEvent | MouseEvent | TouchEvent)} event - The input event\n * which will initialize this Input object.\n * @param {number} identifier - The identifier for this input, so that it can\n * be located in subsequent Event objects.\n */\nclass Input {\n constructor(event, identifier, headless = false) {\n const currentData = new PointerData(event, identifier);\n\n /**\n * The set of elements along the original event's propagation path at the\n * time it was dispatched.\n *\n * @type {WeakSet.<Element>}\n */\n if (headless) {\n this.initialElements = new WeakSet([event.target]);\n } else {\n this.initialElements = new WeakSet(getPropagationPath(event));\n }\n\n /**\n * Holds the initial data from the mousedown / touchstart / pointerdown that\n * began this input.\n *\n * @type {westures-core.PointerData}\n */\n this.initial = currentData;\n\n /**\n * Holds the most current pointer data for this Input.\n *\n * @type {westures-core.PointerData}\n */\n this.current = currentData;\n\n /**\n * Holds the previous pointer data for this Input.\n *\n * @type {westures-core.PointerData}\n */\n this.previous = currentData;\n\n /**\n * The identifier for the pointer / touch / mouse button associated with\n * this input.\n *\n * @type {number}\n */\n this.identifier = identifier;\n }\n\n /**\n * The phase of the input: 'start' or 'move' or 'end' or 'cancel'\n *\n * @type {string}\n */\n get phase() { return this.current.type; }\n\n /**\n * The timestamp of the initiating event for this input.\n *\n * @type {number}\n */\n get startTime() { return this.initial.time; }\n\n /**\n * The amount of time elapsed between the start of this input and its latest\n * event.\n *\n * @type {number}\n */\n get elapsedTime() { return this.current.time - this.initial.time; }\n\n /**\n * @return {number} The distance between the initiating event for this input\n * and its current event.\n */\n totalDistance() {\n return this.initial.point.distanceTo(this.current.point);\n }\n\n /**\n * Saves the given raw event in PointerData form as the current data for this\n * input, pushing the old current data into the previous slot, and tossing\n * out the old previous data.\n *\n * @param {Event} event - The event object to wrap with a PointerData.\n */\n update(event) {\n this.previous = this.current;\n this.current = new PointerData(event, this.identifier);\n }\n}\n\nmodule.exports = Input;\n\n","'use strict';\n\nconst Point2D = require('./Point2D.js');\nconst { PHASE } = require('./constants.js');\n\n/**\n * @private\n * @inner\n * @memberof westures-core.PointerData\n *\n * @return {Event} The Event object which corresponds to the given identifier.\n * Contains clientX, clientY values.\n */\nfunction getEventObject(event, identifier) {\n if (event.changedTouches) {\n return Array.from(event.changedTouches).find(touch => {\n return touch.identifier === identifier;\n });\n }\n return event;\n}\n\n/**\n * Low-level storage of pointer data based on incoming data from an interaction\n * event.\n *\n * @memberof westures-core\n *\n * @param {Event} event - The event object being wrapped.\n * @param {number} identifier - The index of touch if applicable\n */\nclass PointerData {\n constructor(event, identifier) {\n const { clientX, clientY } = getEventObject(event, identifier);\n\n /**\n * The original event object.\n *\n * @type {Event}\n */\n this.event = event;\n\n /**\n * The type or 'phase' of this batch of pointer data. 'start' or 'move' or\n * 'end' or 'cancel'\n *\n * @type {string}\n */\n this.type = PHASE[event.type];\n\n /**\n * The timestamp of the event in milliseconds elapsed since January 1, 1970,\n * 00:00:00 UTC.\n *\n * @type {number}\n */\n this.time = Date.now();\n\n /**\n * The (x,y) coordinate of the event, wrapped in a Point2D.\n *\n * @type {westures-core.Point2D}\n */\n this.point = new Point2D(clientX, clientY);\n }\n}\n\nmodule.exports = PointerData;\n\n","'use strict';\n\n/**\n * The Point2D class stores and operates on 2-dimensional points, represented as\n * x and y coordinates.\n *\n * @memberof westures-core\n *\n * @param {number} [ x=0 ] - The x coordinate of the point.\n * @param {number} [ y=0 ] - The y coordinate of the point.\n */\nclass Point2D {\n constructor(x = 0, y = 0) {\n /**\n * The x coordinate of the point.\n *\n * @type {number}\n */\n this.x = x;\n\n /**\n * The y coordinate of the point.\n *\n * @type {number}\n */\n this.y = y;\n }\n\n /**\n * Calculates the angle between this point and the given point.\n *\n * @param {!westures-core.Point2D} point - Projected point for calculating the\n * angle.\n *\n * @return {number} Radians along the unit circle where the projected\n * point lies.\n */\n angleTo(point) {\n return Math.atan2(point.y - this.y, point.x - this.x);\n }\n\n /**\n * Determine the angle from the centroid to each of the points.\n *\n * @param {!westures-core.Point2D[]} points - the Point2D objects to calculate\n * the angles to.\n *\n * @returns {number[]}\n */\n anglesTo(points) {\n return points.map(point => this.angleTo(point));\n }\n\n /**\n * Determine the average distance from this point to the provided array of\n * points.\n *\n * @param {!westures-core.Point2D[]} points - the Point2D objects to calculate\n * the average distance to.\n *\n * @return {number} The average distance from this point to the provided\n * points.\n */\n averageDistanceTo(points) {\n return this.totalDistanceTo(points) / points.length;\n }\n\n /**\n * Clone this point.\n *\n * @return {westures-core.Point2D} A new Point2D, identical to this point.\n */\n clone() {\n return new Point2D(this.x, this.y);\n }\n\n /**\n * Calculates the distance between two points.\n *\n * @param {!westures-core.Point2D} point - Point to which the distance is\n * calculated.\n *\n * @return {number} The distance between the two points, a.k.a. the\n * hypoteneuse.\n */\n distanceTo(point) {\n return Math.hypot(point.x - this.x, point.y - this.y);\n }\n\n /**\n * Subtract the given point from this point.\n *\n * @param {!westures-core.Point2D} point - Point to subtract from this point.\n *\n * @return {westures-core.Point2D} A new Point2D, which is the result of (this\n * - point).\n */\n minus(point) {\n return new Point2D(\n this.x - point.x,\n this.y - point.y,\n );\n }\n\n /**\n * Return the summation of this point to the given point.\n *\n * @param {!westures-core.Point2D} point - Point to add to this point.\n *\n * @return {westures-core.Point2D} A new Point2D, which is the addition of the\n * two points.\n */\n plus(point) {\n return new Point2D(\n this.x + point.x,\n this.y + point.y,\n );\n }\n\n /**\n * Calculates the total distance from this point to an array of points.\n *\n * @param {!westures-core.Point2D[]} points - The array of Point2D objects to\n * calculate the total distance to.\n *\n * @return {number} The total distance from this point to the provided points.\n */\n totalDistanceTo(points) {\n return points.reduce((d, p) => d + this.distanceTo(p), 0);\n }\n\n /**\n * Calculates the centroid of a list of points.\n *\n * @param {westures-core.Point2D[]} points - The array of Point2D objects for\n * which to calculate the centroid.\n *\n * @return {westures-core.Point2D} The centroid of the provided points.\n */\n static centroid(points = []) {\n if (points.length === 0) return null;\n\n const total = Point2D.sum(points);\n total.x /= points.length;\n total.y /= points.length;\n return total;\n }\n\n /**\n * Calculates the sum of the given points.\n *\n * @param {westures-core.Point2D[]} points - The Point2D objects to sum up.\n *\n * @return {westures-core.Point2D} A new Point2D representing the sum of the\n * given points.\n */\n static sum(points = []) {\n return points.reduce(\n (total, pt) => {\n total.x += pt.x;\n total.y += pt.y;\n return total;\n },\n new Point2D(0, 0),\n );\n }\n}\n\nmodule.exports = Point2D;\n\n","'use strict';\n\n/**\n * List of events that trigger the cancel phase.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst CANCEL_EVENTS = [\n 'blur',\n 'pointercancel',\n 'touchcancel',\n 'mouseleave',\n];\n\n/**\n * List of keyboard events that trigger a restart.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst KEYBOARD_EVENTS = [\n 'keydown',\n 'keyup',\n];\n\n/**\n * List of mouse events to listen to.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst MOUSE_EVENTS = [\n 'mousedown',\n 'mousemove',\n 'mouseup',\n];\n\n/**\n * List of pointer events to listen to.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst POINTER_EVENTS = [\n 'pointerdown',\n 'pointermove',\n 'pointerup',\n];\n\n/**\n * List of touch events to listen to.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst TOUCH_EVENTS = [\n 'touchend',\n 'touchmove',\n 'touchstart',\n];\n\n/**\n * List of potentially state-modifying keys.\n * Entries are: ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst STATE_KEYS = [\n 'altKey',\n 'ctrlKey',\n 'metaKey',\n 'shiftKey',\n];\n\n/**\n * List of the 'key' values on KeyboardEvent objects of the potentially\n * state-modifying keys.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst STATE_KEY_STRINGS = [\n 'Alt',\n 'Control',\n 'Meta',\n 'Shift',\n];\n\n/**\n * The cancel phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst CANCEL = 'cancel';\n\n/**\n * The end phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst END = 'end';\n\n/**\n * The move phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst MOVE = 'move';\n\n/**\n * The start phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst START = 'start';\n\n/**\n * The recognized phases.\n *\n * @memberof westures-core\n * @type {list.<string>}\n */\nconst PHASES = [START, MOVE, END, CANCEL];\n\n/**\n * Object that normalizes the names of window events to be either of type start,\n * move, end, or cancel.\n *\n * @memberof westures-core\n * @type {object}\n */\nconst PHASE = {\n blur: CANCEL,\n pointercancel: CANCEL,\n touchcancel: CANCEL,\n\n mouseup: END,\n pointerup: END,\n touchend: END,\n\n mousemove: MOVE,\n pointermove: MOVE,\n touchmove: MOVE,\n\n mousedown: START,\n pointerdown: START,\n touchstart: START,\n};\n\nmodule.exports = {\n CANCEL_EVENTS,\n KEYBOARD_EVENTS,\n MOUSE_EVENTS,\n POINTER_EVENTS,\n TOUCH_EVENTS,\n\n STATE_KEYS,\n STATE_KEY_STRINGS,\n\n CANCEL,\n END,\n MOVE,\n START,\n\n PHASE,\n PHASES,\n};\n\n","'use strict';\n\nconst PI_2 = 2 * Math.PI;\nconst PI_NVE = -Math.PI;\n\n/**\n * Helper function to regulate angular differences, so they don't jump from 0 to\n * 2 * PI or vice versa.\n *\n * @memberof westures-core\n *\n * @param {number} a - Angle in radians.\n * @param {number} b - Angle in radians.\n\n * @return {number} c, given by: c = a - b such that |c| < PI\n */\nfunction angularDifference(a, b) {\n let diff = a - b;\n if (diff < PI_NVE) {\n diff += PI_2;\n } else if (diff > Math.PI) {\n diff -= PI_2;\n }\n return diff;\n}\n\n/**\n * In case event.composedPath() is not available.\n *\n * @memberof westures-core\n *\n * @param {Event} event\n *\n * @return {Element[]} The elements along the composed path of the event.\n */\nfunction getPropagationPath(event) {\n if (typeof event.composedPath === 'function') {\n return event.composedPath();\n }\n\n const path = [];\n for (let node = event.target; node !== document; node = node.parentNode) {\n path.push(node);\n }\n path.push(document);\n path.push(window);\n\n return path;\n}\n\n/**\n * Performs a set filter operation.\n *\n * @memberof westures-core\n *\n * @param {Set} set - The set to filter.\n * @param {Function} predicate - Function to test elements of 'set'. Receives\n * one argument: the current set element.\n *\n * @return {Set} Set consisting of elements in 'set' for which 'predicate' is\n * true.\n */\nfunction setFilter(set, predicate) {\n const result = new Set();\n set.forEach(element => {\n if (predicate(element)) {\n result.add(element);\n }\n });\n return result;\n}\n\n/**\n * Performs a set difference operation.\n *\n * @memberof westures-core\n *\n * @param {Set} left - Base set.\n * @param {Set} right - Set of elements to remove from 'left'.\n *\n * @return {Set} Set consisting of elements in 'left' that are not in\n * 'right'.\n */\nfunction setDifference(left, right) {\n return setFilter(left, element => !right.has(element));\n}\n\nmodule.exports = {\n angularDifference,\n getPropagationPath,\n setDifference,\n setFilter,\n};\n\n","'use strict';\n\nconst State = require('./State.js');\nconst {\n CANCEL_EVENTS,\n KEYBOARD_EVENTS,\n MOUSE_EVENTS,\n POINTER_EVENTS,\n TOUCH_EVENTS,\n\n STATE_KEY_STRINGS,\n\n PHASE,\n\n CANCEL,\n END,\n START,\n} = require('./constants.js');\nconst {\n setDifference,\n setFilter,\n} = require('./utils.js');\n\n/**\n * Allows the user to specify the control region which will listen for user\n * input events.\n *\n * @memberof westures-core\n *\n * @param {Element} [element=null] - The element which should listen to input\n * events. If not provided, will be set to the window unless operating in\n * \"headless\" mode.\n * @param {object} [options]\n * @param {boolean} [options.capture=false] - Whether the region uses the\n * capture phase of input events. If false, uses the bubbling phase.\n * @param {boolean} [options.preferPointer=true] - If false, the region listens\n * to mouse/touch events instead of pointer events.\n * @param {boolean} [options.preventDefault=true] - Whether the default\n * browser functionality should be disabled. This option should most likely be\n * ignored. Here there by dragons if set to false.\n * @param {string} [options.touchAction='none'] - Value to set the CSS\n * 'touch-action' property to on elements added to the region.\n * @param {boolean} [options.headless=false] - Set to true to turn on \"headless\"\n * mode. This mode is intended for use outside of a browser environment. It does\n * not listen to window events, so instead you will have to send events directly\n * into the region. Pointer down/move/up events should be sent to\n * Region.arbitrate(event), cancel events should be sent to\n * Region.cancel(event), and keyboard events should be sent to\n * Region.handleKeyboardEvent(event). You do not need to supply an element to\n * the Region constructor in this mode, but you will still need to attach\n * elements to Gestures, and the events you pass in should specify event.target\n * appropriately, in order to select which gestures to run.\n */\nclass Region {\n constructor(element = null, options = {}) {\n options = { ...Region.DEFAULTS, ...options };\n if (element === null) {\n if (options.headless) {\n element = null;\n } else {\n element = window;\n }\n }\n\n /**\n * The list of relations between elements, their gestures, and the handlers.\n *\n * @type {Set.<westures-core.Gesture>}\n */\n this.gestures = new Set();\n\n /**\n * The list of active gestures for the current input session.\n *\n * @type {Set.<westures-core.Gesture>}\n */\n this.activeGestures = new Set();\n\n /**\n * The base list of potentially active gestures for the current input\n * session.\n *\n * @type {Set.<westures-core.Gesture>}\n */\n this.potentialGestures = new Set();\n\n /**\n * The element being bound to.\n *\n * @type {Element}\n */\n this.element = element;\n\n /**\n * The user-supplied options for the Region.\n *\n * @type {object}\n */\n this.options = options;\n\n /**\n * The internal state object for a Region. Keeps track of inputs.\n *\n * @type {westures-core.State}\n */\n this.state = new State(this.element, options.headless);\n\n if (!options.headless) {\n // Begin operating immediately.\n this.activate();\n }\n }\n\n /**\n * Activates the region by adding event listeners for all appropriate input\n * events to the region's element.\n *\n * @private\n */\n activate() {\n /*\n * Listening to both mouse and touch comes with the difficulty that\n * preventDefault() must be called to prevent both events from iterating\n * through the system. However I have left it as an option to the end user,\n * which defaults to calling preventDefault(), in case there's a use-case I\n * haven't considered or am not aware of.\n *\n * It also may be a good idea to keep regions small in large pages.\n *\n * See:\n * https://www.html5rocks.com/en/mobile/touchandmouse/\n * https://developer.mozilla.org/en-US/docs/Web/API/Touch_events\n * https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events\n */\n let eventNames = [];\n if (this.options.preferPointer && window.PointerEvent) {\n eventNames = POINTER_EVENTS;\n } else {\n eventNames = MOUSE_EVENTS.concat(TOUCH_EVENTS);\n }\n\n // Bind detected browser events to the region element.\n const arbitrate = this.arbitrate.bind(this);\n eventNames.forEach(eventName => {\n this.element.addEventListener(eventName, arbitrate, {\n capture: this.options.capture,\n once: false,\n passive: false,\n });\n });\n\n const cancel = this.cancel.bind(this);\n CANCEL_EVENTS.forEach(eventName => {\n window.addEventListener(eventName, cancel);\n });\n\n const handleKeyboardEvent = this.handleKeyboardEvent.bind(this);\n KEYBOARD_EVENTS.forEach(eventName => {\n window.addEventListener(eventName, handleKeyboardEvent);\n });\n }\n\n /**\n * Handles a cancel event. Resets the state and the active / potential gesture\n * lists.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n */\n cancel(event) {\n if (\n this.options.preventDefault && typeof event.preventDefault === 'function'\n ) {\n event.preventDefault();\n }\n this.state.inputs.forEach(input => {\n input.update(event);\n });\n this.activeGestures.forEach(gesture => {\n gesture.evaluateHook(CANCEL, this.state);\n });\n this.state = new State(this.element, this.options.headless);\n this.resetActiveGestures();\n }\n\n /**\n * Handles a keyboard event, triggering a restart of any gestures that need\n * it.\n *\n * @private\n * @param {KeyboardEvent} event - The keyboard event.\n */\n handleKeyboardEvent(event) {\n if (STATE_KEY_STRINGS.indexOf(event.key) >= 0) {\n this.state.event = event;\n const oldActiveGestures = this.activeGestures;\n this.setActiveGestures();\n\n setDifference(oldActiveGestures, this.activeGestures).forEach(gesture => {\n gesture.evaluateHook(END, this.state);\n });\n setDifference(this.activeGestures, oldActiveGestures).forEach(gesture => {\n gesture.evaluateHook(START, this.state);\n });\n }\n }\n\n /**\n * Resets the active gestures.\n *\n * @private\n */\n resetActiveGestures() {\n this.potentialGestures = new Set();\n this.activeGestures = new Set();\n }\n\n /**\n * Selects active gestures from the list of potentially active gestures.\n *\n * @private\n */\n setActiveGestures() {\n this.activeGestures = setFilter(this.potentialGestures, gesture => {\n return gesture.isEnabled(this.state);\n });\n }\n\n /**\n * Selects the potentially active gestures.\n *\n * @private\n */\n setPotentialGestures() {\n const input = this.state.inputs[0];\n this.potentialGestures = setFilter(this.gestures, gesture => {\n return input.initialElements.has(gesture.element);\n });\n }\n\n /**\n * Selects the gestures that are active for the current input sequence.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n * @param {boolean} isInitial - Whether this is an initial contact.\n */\n updateActiveGestures(event, isInitial) {\n if (PHASE[event.type] === START) {\n if (isInitial) {\n this.setPotentialGestures();\n }\n this.setActiveGestures();\n }\n }\n\n /**\n * Evaluates whether the current input session has completed.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n */\n pruneActiveGestures(event) {\n if (PHASE[event.type] === END) {\n if (this.state.hasNoInputs()) {\n this.resetActiveGestures();\n } else {\n this.setActiveGestures();\n }\n }\n }\n\n /**\n * All input events flow through this function. It makes sure that the input\n * state is maintained, determines which gestures to analyze based on the\n * initial position of the inputs, calls the relevant gesture hooks, and\n * dispatches gesture data.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n */\n arbitrate(event) {\n const isInitial = this.state.hasNoInputs();\n this.state.updateAllInputs(event);\n this.updateActiveGestures(event, isInitial);\n\n if (this.activeGestures.size > 0) {\n if (\n this.options.preventDefault &&\n typeof event.preventDefault === 'function'\n ) event.preventDefault();\n\n this.activeGestures.forEach(gesture => {\n gesture.evaluateHook(PHASE[event.type], this.state);\n });\n }\n\n this.state.clearEndedInputs();\n this.pruneActiveGestures(event);\n }\n\n /**\n * Adds the given gesture to the region.\n *\n * @param {westures-core.Gesture} gesture - Instantiated gesture to add.\n */\n addGesture(gesture) {\n if (!this.options.headless) {\n gesture.element.style.touchAction = this.options.touchAction;\n }\n this.gestures.add(gesture);\n }\n\n /**\n * Removes the given gesture from the region.\n *\n * @param {westures-core.Gesture} gesture - Instantiated gesture to add.\n */\n removeGesture(gesture) {\n this.gestures.delete(gesture);\n this.potentialGestures.delete(gesture);\n this.activeGestures.delete(gesture);\n }\n\n /**\n * Retrieves Gestures by their associated element.\n *\n * @param {Element} element - The element for which to find gestures.\n *\n * @return {westures-core.Gesture[]} Gestures to which the element is bound.\n */\n getGesturesByElement(element) {\n return setFilter(this.gestures, gesture => gesture.element === element);\n }\n\n /**\n * Remove all gestures bound to the given element.\n *\n * @param {Element} element - The element to unbind.\n */\n removeGesturesByElement(element) {\n this.getGesturesByElement(element).forEach(g => this.removeGesture(g));\n }\n}\n\nRegion.DEFAULTS = {\n capture: false,\n preferPointer: true,\n preventDefault: true,\n touchAction: 'none',\n headless: false,\n};\n\nmodule.exports = Region;\n","'use strict';\n\nconst {\n CANCEL,\n END,\n MOVE,\n PHASE,\n START,\n MOUSE_EVENTS,\n POINTER_EVENTS,\n TOUCH_EVENTS,\n} = require('./constants.js');\nconst Input = require('./Input.js');\nconst Point2D = require('./Point2D.js');\n\nconst symbols = {\n inputs: Symbol.for('inputs'),\n};\n\n/**\n * Keeps track of currently active and ending input points on the interactive\n * surface.\n *\n * @memberof westures-core\n *\n * @param {Element} element - The element underpinning the associated Region.\n * @param {boolean} [headless=false] - Whether westures is operating in\n * \"headless\" mode.\n */\nclass State {\n constructor(element, headless = false) {\n /**\n * Keep a reference to the element for the associated region.\n *\n * @type {Element}\n */\n this.element = element;\n\n /**\n * Whether westures is operating in \"headless\" mode.\n *\n * @type {boolean}\n */\n this.headless = headless;\n\n /**\n * Keeps track of the current Input objects.\n *\n * @alias [@@inputs]\n * @type {Map.<westures-core.Input>}\n * @memberof westure-core.State\n */\n this[symbols.inputs] = new Map();\n\n /**\n * All currently valid inputs, including those that have ended.\n *\n * @type {westures-core.Input[]}\n */\n this.inputs = [];\n\n /**\n * The array of currently active inputs, sourced from the current Input\n * objects. \"Active\" is defined as not being in the 'end' phase.\n *\n * @type {westures-core.Input[]}\n */\n this.active = [];\n\n /**\n * The array of latest point data for the currently active inputs, sourced\n * from this.active.\n *\n * @type {westures-core.Point2D[]}\n */\n this.activePoints = [];\n\n /**\n * The centroid of the currently active points.\n *\n * @type {westures-core.Point2D}\n */\n this.centroid = {};\n\n /**\n * The latest event that the state processed.\n *\n * @type {Event}\n */\n this.event = null;\n }\n\n /**\n * Deletes all inputs that are in the 'end' phase.\n */\n clearEndedInputs() {\n this[symbols.inputs].forEach((v, k) => {\n if (v.phase === 'end') this[symbols.inputs].delete(k);\n });\n }\n\n /**\n * @param {string} phase - One of 'start', 'move', 'end', or 'cancel'.\n *\n * @return {westures-core.Input[]} Inputs in the given phase.\n */\n getInputsInPhase(phase) {\n return this.inputs.filter(i => i.phase === phase);\n }\n\n /**\n * @param {string} phase - One of 'start', 'move', 'end', or 'cancel'.\n *\n * @return {westures-core.Input[]} Inputs <b>not</b> in the given phase.\n */\n getInputsNotInPhase(phase) {\n return this.inputs.filter(i => i.phase !== phase);\n }\n\n /**\n * @return {boolean} True if there are no active inputs. False otherwise.\n */\n hasNoInputs() {\n return this[symbols.inputs].size === 0;\n }\n\n /**\n * Update the input with the given identifier using the given event.\n *\n * @private\n *\n * @param {Event} event - The event being captured.\n * @param {number} identifier - The identifier of the input to update.\n */\n updateInput(event, identifier) {\n switch (PHASE[event.type]) {\n case START:\n this[symbols.inputs].set(\n identifier,\n new Input(event, identifier, this.headless),\n );\n if (!this.headless) {\n try {\n this.element.setPointerCapture(identifier);\n } catch (e) {\n // NOP: Optional operation failed.\n }\n }\n break;\n\n // All of 'end', 'move', and 'cancel' perform updates, hence the\n // following fall-throughs\n case END:\n if (!this.headless) {\n try {\n this.element.releasePointerCapture(identifier);\n } catch (e) {\n // NOP: Optional operation failed.\n }\n }\n case CANCEL:\n case MOVE:\n if (this[symbols.inputs].has(identifier)) {\n this[symbols.inputs].get(identifier).update(event);\n }\n break;\n\n default:\n console.warn(`Unrecognized event type: ${event.type}`);\n }\n }\n\n /**\n * Updates the inputs with new information based upon a new event being fired.\n *\n * @private\n * @param {Event} event - The event being captured.\n */\n updateAllInputs(event) {\n if (POINTER_EVENTS.includes(event.type)) {\n this.updateInput(event, event.pointerId);\n } else if (MOUSE_EVENTS.includes(event.type)) {\n if (event.button === 0) {\n this.updateInput(event, event.button);\n }\n } else if (TOUCH_EVENTS.includes(event.type)) {\n Array.from(event.changedTouches).forEach(touch => {\n this.updateInput(event, touch.identifier);\n });\n } else {\n throw new Error(`Unexpected event type: ${event.type}`);\n }\n this.updateFields(event);\n }\n\n /**\n * Updates the convenience fields.\n *\n * @private\n * @param {Event} event - Event with which to update the convenience fields.\n */\n updateFields(event) {\n this.inputs = Array.from(this[symbols.inputs].values());\n this.active = this.getInputsNotInPhase('end');\n this.activePoints = this.active.map(i => i.current.point);\n this.centroid = Point2D.centroid(this.activePoints);\n this.event = event;\n }\n}\n\nmodule.exports = State;\n\n","'use strict';\n\nconst cascade = Symbol('cascade');\nconst smooth = Symbol('smooth');\n\n/**\n * Determines whether to apply smoothing. Smoothing is on by default but turned\n * off if either:<br>\n * 1. The user explicitly requests that it be turned off.<br>\n * 2. The active pointer is not \"coarse\".<br>\n *\n * @see {@link\n * https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia}\n *\n * @inner\n * @memberof westures-core.Smoothable\n *\n * @param {boolean} isRequested - Whether smoothing was requested by the user.\n *\n * @returns {boolean} Whether to apply smoothing.\n */\nfunction smoothingIsApplicable(isRequested) {\n if (isRequested) {\n try {\n return window.matchMedia('(pointer: coarse)').matches;\n } catch (e) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * A Smoothable datatype is one that is capable of smoothing out a series of\n * values as they come in, one at a time, providing a more consistent series. It\n * does this by creating some inertia in the values using a cascading average.\n * (For those who are interested in such things, this effectively means that it\n * provides a practical application of Zeno's Dichotomy).\n *\n * @example\n * const x = new Smoothable({ identity: 1 });\n * const a = x.next(1); // 1.0\n * const b = x.next(1.2); // 1.1\n * const c = x.next(0.9); // 1.0\n * const d = x.next(0.6); // 0.8\n * const e = x.next(1.2); // 1.0\n * const f = x.next(1.6); // 1.3\n * x.restart();\n * const g = x.next(0); // 0.5\n *\n * @memberof westures-core\n *\n * @param {Object} [options]\n * @param {boolean} [options.applySmoothing=true] Whether to apply smoothing to\n * the data.\n * @param {*} [options.identity=0] The identity value of this smoothable data.\n */\nclass Smoothable {\n constructor(options = {}) {\n const final_options = { ...Smoothable.DEFAULTS, ...options };\n\n /**\n * The function through which smoothed emits are passed.\n *\n * @method\n * @param {*} data - The data to emit.\n *\n * @return {*} The smoothed out data.\n */\n this.next = null;\n if (smoothingIsApplicable(final_options.applySmoothing)) {\n this.next = this[smooth].bind(this);\n } else {\n this.next = data => data;\n }\n\n /**\n * The \"identity\" value of the data that will be smoothed.\n *\n * @type {*}\n * @default 0\n */\n this.identity = final_options.identity;\n\n /**\n * The cascading average of outgoing values.\n *\n * @memberof westures-core.Smoothable\n * @alias [@@cascade]\n * @type {object}\n */\n this[cascade] = this.identity;\n }\n\n /**\n * Restart the Smoothable gesture.\n */\n restart() {\n this[cascade] = this.identity;\n }\n\n /**\n * Smooth out the outgoing data.\n *\n * @memberof westures-core.Smoothable\n * @alias [@@smooth]\n * @param {object} data - The next batch of data to emit.\n *\n * @return {?object}\n */\n [smooth](data) {\n const average = this.average(this[cascade], data);\n this[cascade] = average;\n return average;\n }\n\n /**\n * Average out two values, as part of the smoothing algorithm. Override this\n * method if the data being smoothed is not a Number.\n *\n * @param {number} a\n * @param {number} b\n *\n * @return {number} The average of 'a' and 'b'\n */\n average(a, b) {\n return (a + b) / 2;\n }\n}\n\nSmoothable.DEFAULTS = {\n applySmoothing: true,\n identity: 0,\n};\n\nmodule.exports = Smoothable;\n\n"],"names":[],"version":3,"file":"index.js.map"}
1
+ {"mappings":"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","sources":["index.js","src/Gesture.js","src/Input.js","src/PointerData.js","src/Point2D.js","src/constants.js","src/utils.js","src/Region.js","src/State.js","src/Smoothable.js"],"sourcesContent":["/**\n * The global API interface for westures-core. Exposes all classes, constants,\n * and routines used by the package. Use responsibly.\n *\n * @namespace westures-core\n */\n\n'use strict';\n\nconst Gesture = require('./src/Gesture.js');\nconst Input = require('./src/Input.js');\nconst Point2D = require('./src/Point2D.js');\nconst PointerData = require('./src/PointerData.js');\nconst Region = require('./src/Region.js');\nconst Smoothable = require('./src/Smoothable.js');\nconst State = require('./src/State.js');\nconst constants = require('./src/constants.js');\nconst utils = require('./src/utils.js');\n\nmodule.exports = {\n Gesture,\n Input,\n Point2D,\n PointerData,\n Region,\n Smoothable,\n State,\n ...constants,\n ...utils,\n};\n\n","'use strict';\n\nlet g_id = 0;\n\n/**\n * The Gesture class that all gestures inherit from. A custom gesture class will\n * need to override some or all of the four phase \"hooks\": start, move, end, and\n * cancel.\n *\n * @memberof westures-core\n *\n * @param {string} type - The name of the gesture.\n * @param {Element} element - The element to which to associate the gesture.\n * @param {Function} handler - The function handler to execute when a gesture\n * is recognized on the associated element.\n * @param {object} [options] - Generic gesture options\n * @param {westures-core.STATE_KEYS[]} [options.enableKeys=[]] - List of keys\n * which will enable the gesture. The gesture will not be recognized unless one\n * of these keys is pressed while the interaction occurs. If not specified or an\n * empty list, the gesture is treated as though the enable key is always down.\n * @param {westures-core.STATE_KEYS[]} [options.disableKeys=[]] - List of keys\n * which will disable the gesture. The gesture will not be recognized if one of\n * these keys is pressed while the interaction occurs. If not specified or an\n * empty list, the gesture is treated as though the disable key is never down.\n * @param {number} [options.minInputs=1] - The minimum number of pointers that\n * must be active for the gesture to be recognized. Uses >=.\n * @param {number} [options.maxInputs=Number.MAX_VALUE] - The maximum number of\n * pointers that may be active for the gesture to be recognized. Uses <=.\n */\nclass Gesture {\n constructor(type, element, handler, options = {}) {\n if (typeof type !== 'string') {\n throw new TypeError('Gestures require a string type / name');\n }\n\n /**\n * The name of the gesture. (e.g. 'pan' or 'tap' or 'pinch').\n *\n * @type {string}\n */\n this.type = type;\n\n /**\n * The unique identifier for each gesture. This allows for distinctions\n * across instances of Gestures that are created on the fly (e.g.\n * gesture-tap-1, gesture-tap-2).\n *\n * @type {string}\n */\n this.id = `gesture-${this.type}-${g_id++}`;\n\n /**\n * The element to which to associate the gesture.\n *\n * @type {Element}\n */\n this.element = element;\n\n /**\n * The function handler to execute when the gesture is recognized on the\n * associated element.\n *\n * @type {Function}\n */\n this.handler = handler;\n\n /**\n * The options. Can usually be adjusted live, though be careful doing this.\n *\n * @type {object}\n */\n this.options = { ...Gesture.DEFAULTS, ...options };\n }\n\n /**\n * Determines whether this gesture is enabled.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {boolean} true if enabled, false otherwise.\n */\n isEnabled(state) {\n const count = state.active.length;\n const event = state.event;\n const { enableKeys, disableKeys, minInputs, maxInputs } = this.options;\n\n return (minInputs <= count) && (maxInputs >= count) &&\n (enableKeys.length === 0 || enableKeys.some(k => event[k])) &&\n !disableKeys.some(k => event[k]);\n }\n\n /**\n * Event hook for the start phase of a gesture.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n start() {\n return null;\n }\n\n /**\n * Event hook for the move phase of a gesture.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n move() {\n return null;\n }\n\n /**\n * Event hook for the end phase of a gesture.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n end() {\n return null;\n }\n\n /**\n * Event hook for when an input is cancelled.\n *\n * @param {westures-core.State} state - The input state object of the current\n * region.\n *\n * @return {?Object} Gesture is considered recognized if an Object is\n * returned.\n */\n cancel() {\n return null;\n }\n\n /**\n * Evalutes the given gesture hook, and dispatches any data that is produced\n * by calling [recognize]{@link westures-core.Gesture#recognize}.\n *\n * @param {string} hook - Must be one of 'start', 'move', 'end', or 'cancel'.\n * @param {westures-core.State} state - The current State instance.\n */\n evaluateHook(hook, state) {\n const data = this[hook](state);\n if (data) {\n this.recognize(hook, state, data);\n }\n }\n\n /**\n * Recognize a Gesture by calling the handler. Standardizes the way the\n * handler is called so that classes extending Gesture can circumvent the\n * evaluateHook approach but still provide results that have a common format.\n *\n * Note that the properties in the \"data\" object will receive priority when\n * constructing the results. This can be used to override standard results\n * such as the phase or the centroid.\n *\n * @param {string} hook - Must be one of 'start', 'move', 'end', or 'cancel'.\n * @param {westures-core.State} state - current input state.\n * @param {Object} data - Results data specific to the recognized gesture.\n */\n recognize(hook, state, data) {\n this.handler({\n centroid: state.centroid,\n event: state.event,\n phase: hook,\n type: this.type,\n target: this.element,\n ...data,\n });\n }\n}\n\nGesture.DEFAULTS = {\n enableKeys: [],\n disableKeys: [],\n minInputs: 1,\n maxInputs: Number.MAX_VALUE,\n};\n\nmodule.exports = Gesture;\n\n","'use strict';\n\nconst PointerData = require('./PointerData.js');\nconst { getPropagationPath } = require('./utils.js');\n\n/**\n * Tracks a single input and contains information about the current, previous,\n * and initial events.\n *\n * @memberof westures-core\n *\n * @param {(PointerEvent | MouseEvent | TouchEvent)} event - The input event\n * which will initialize this Input object.\n * @param {number} identifier - The identifier for this input, so that it can\n * be located in subsequent Event objects.\n */\nclass Input {\n constructor(event, identifier, headless = false) {\n const currentData = new PointerData(event, identifier);\n\n /**\n * The set of elements along the original event's propagation path at the\n * time it was dispatched.\n *\n * @type {WeakSet.<Element>}\n */\n if (headless) {\n this.initialElements = new WeakSet([event.target]);\n } else {\n this.initialElements = new WeakSet(getPropagationPath(event));\n }\n\n /**\n * Holds the initial data from the mousedown / touchstart / pointerdown that\n * began this input.\n *\n * @type {westures-core.PointerData}\n */\n this.initial = currentData;\n\n /**\n * Holds the most current pointer data for this Input.\n *\n * @type {westures-core.PointerData}\n */\n this.current = currentData;\n\n /**\n * Holds the previous pointer data for this Input.\n *\n * @type {westures-core.PointerData}\n */\n this.previous = currentData;\n\n /**\n * The identifier for the pointer / touch / mouse button associated with\n * this input.\n *\n * @type {number}\n */\n this.identifier = identifier;\n }\n\n /**\n * The phase of the input: 'start' or 'move' or 'end' or 'cancel'\n *\n * @type {string}\n */\n get phase() { return this.current.type; }\n\n /**\n * The timestamp of the initiating event for this input.\n *\n * @type {number}\n */\n get startTime() { return this.initial.time; }\n\n /**\n * The amount of time elapsed between the start of this input and its latest\n * event.\n *\n * @type {number}\n */\n get elapsedTime() { return this.current.time - this.initial.time; }\n\n /**\n * @return {number} The distance between the initiating event for this input\n * and its current event.\n */\n totalDistance() {\n return this.initial.point.distanceTo(this.current.point);\n }\n\n /**\n * Saves the given raw event in PointerData form as the current data for this\n * input, pushing the old current data into the previous slot, and tossing\n * out the old previous data.\n *\n * @param {Event} event - The event object to wrap with a PointerData.\n */\n update(event) {\n this.previous = this.current;\n this.current = new PointerData(event, this.identifier);\n }\n}\n\nmodule.exports = Input;\n\n","'use strict';\n\nconst Point2D = require('./Point2D.js');\nconst { PHASE } = require('./constants.js');\n\n/**\n * @private\n * @inner\n * @memberof westures-core.PointerData\n *\n * @return {Event} The Event object which corresponds to the given identifier.\n * Contains clientX, clientY values.\n */\nfunction getEventObject(event, identifier) {\n if (event.changedTouches) {\n return Array.from(event.changedTouches).find(touch => {\n return touch.identifier === identifier;\n });\n }\n return event;\n}\n\n/**\n * Low-level storage of pointer data based on incoming data from an interaction\n * event.\n *\n * @memberof westures-core\n *\n * @param {Event} event - The event object being wrapped.\n * @param {number} identifier - The index of touch if applicable\n */\nclass PointerData {\n constructor(event, identifier) {\n const { clientX, clientY } = getEventObject(event, identifier);\n\n /**\n * The original event object.\n *\n * @type {Event}\n */\n this.event = event;\n\n /**\n * The type or 'phase' of this batch of pointer data. 'start' or 'move' or\n * 'end' or 'cancel'\n *\n * @type {string}\n */\n this.type = PHASE[event.type];\n\n /**\n * The timestamp of the event in milliseconds elapsed since January 1, 1970,\n * 00:00:00 UTC.\n *\n * @type {number}\n */\n this.time = Date.now();\n\n /**\n * The (x,y) coordinate of the event, wrapped in a Point2D.\n *\n * @type {westures-core.Point2D}\n */\n this.point = new Point2D(clientX, clientY);\n }\n}\n\nmodule.exports = PointerData;\n\n","'use strict';\n\n/**\n * The Point2D class stores and operates on 2-dimensional points, represented as\n * x and y coordinates.\n *\n * @memberof westures-core\n *\n * @param {number} [ x=0 ] - The x coordinate of the point.\n * @param {number} [ y=0 ] - The y coordinate of the point.\n */\nclass Point2D {\n constructor(x = 0, y = 0) {\n /**\n * The x coordinate of the point.\n *\n * @type {number}\n */\n this.x = x;\n\n /**\n * The y coordinate of the point.\n *\n * @type {number}\n */\n this.y = y;\n }\n\n /**\n * Calculates the angle between this point and the given point.\n *\n * @param {!westures-core.Point2D} point - Projected point for calculating the\n * angle.\n *\n * @return {number} Radians along the unit circle where the projected\n * point lies.\n */\n angleTo(point) {\n return Math.atan2(point.y - this.y, point.x - this.x);\n }\n\n /**\n * Determine the angle from the centroid to each of the points.\n *\n * @param {!westures-core.Point2D[]} points - the Point2D objects to calculate\n * the angles to.\n *\n * @returns {number[]}\n */\n anglesTo(points) {\n return points.map(point => this.angleTo(point));\n }\n\n /**\n * Determine the average distance from this point to the provided array of\n * points.\n *\n * @param {!westures-core.Point2D[]} points - the Point2D objects to calculate\n * the average distance to.\n *\n * @return {number} The average distance from this point to the provided\n * points.\n */\n averageDistanceTo(points) {\n return this.totalDistanceTo(points) / points.length;\n }\n\n /**\n * Clone this point.\n *\n * @return {westures-core.Point2D} A new Point2D, identical to this point.\n */\n clone() {\n return new Point2D(this.x, this.y);\n }\n\n /**\n * Calculates the distance between two points.\n *\n * @param {!westures-core.Point2D} point - Point to which the distance is\n * calculated.\n *\n * @return {number} The distance between the two points, a.k.a. the\n * hypoteneuse.\n */\n distanceTo(point) {\n return Math.hypot(point.x - this.x, point.y - this.y);\n }\n\n /**\n * Subtract the given point from this point.\n *\n * @param {!westures-core.Point2D} point - Point to subtract from this point.\n *\n * @return {westures-core.Point2D} A new Point2D, which is the result of (this\n * - point).\n */\n minus(point) {\n return new Point2D(\n this.x - point.x,\n this.y - point.y,\n );\n }\n\n /**\n * Return the summation of this point to the given point.\n *\n * @param {!westures-core.Point2D} point - Point to add to this point.\n *\n * @return {westures-core.Point2D} A new Point2D, which is the addition of the\n * two points.\n */\n plus(point) {\n return new Point2D(\n this.x + point.x,\n this.y + point.y,\n );\n }\n\n /**\n * Calculates the total distance from this point to an array of points.\n *\n * @param {!westures-core.Point2D[]} points - The array of Point2D objects to\n * calculate the total distance to.\n *\n * @return {number} The total distance from this point to the provided points.\n */\n totalDistanceTo(points) {\n return points.reduce((d, p) => d + this.distanceTo(p), 0);\n }\n\n /**\n * Calculates the centroid of a list of points.\n *\n * @param {westures-core.Point2D[]} points - The array of Point2D objects for\n * which to calculate the centroid.\n *\n * @return {westures-core.Point2D} The centroid of the provided points.\n */\n static centroid(points = []) {\n if (points.length === 0) return null;\n\n const total = Point2D.sum(points);\n total.x /= points.length;\n total.y /= points.length;\n return total;\n }\n\n /**\n * Calculates the sum of the given points.\n *\n * @param {westures-core.Point2D[]} points - The Point2D objects to sum up.\n *\n * @return {westures-core.Point2D} A new Point2D representing the sum of the\n * given points.\n */\n static sum(points = []) {\n return points.reduce(\n (total, pt) => {\n total.x += pt.x;\n total.y += pt.y;\n return total;\n },\n new Point2D(0, 0),\n );\n }\n}\n\nmodule.exports = Point2D;\n\n","'use strict';\n\n/**\n * List of events that trigger the cancel phase.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst CANCEL_EVENTS = [\n 'blur',\n 'contextmenu',\n 'pointercancel',\n 'touchcancel',\n 'mouseleave',\n];\n\n/**\n * List of keyboard events that trigger a restart.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst KEYBOARD_EVENTS = [\n 'keydown',\n 'keyup',\n];\n\n/**\n * List of mouse events to listen to.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst MOUSE_EVENTS = [\n 'mousedown',\n 'mousemove',\n 'mouseup',\n];\n\n/**\n * List of pointer events to listen to.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst POINTER_EVENTS = [\n 'pointerdown',\n 'pointermove',\n 'pointerup',\n];\n\n/**\n * List of touch events to listen to.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst TOUCH_EVENTS = [\n 'touchend',\n 'touchmove',\n 'touchstart',\n];\n\n/**\n * List of potentially state-modifying keys.\n * Entries are: ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'].\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst STATE_KEYS = [\n 'altKey',\n 'ctrlKey',\n 'metaKey',\n 'shiftKey',\n];\n\n/**\n * List of the 'key' values on KeyboardEvent objects of the potentially\n * state-modifying keys.\n *\n * @memberof westures-core\n * @type {string[]}\n */\nconst STATE_KEY_STRINGS = [\n 'Alt',\n 'Control',\n 'Meta',\n 'Shift',\n];\n\n/**\n * The cancel phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst CANCEL = 'cancel';\n\n/**\n * The end phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst END = 'end';\n\n/**\n * The move phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst MOVE = 'move';\n\n/**\n * The start phase.\n *\n * @memberof westures-core\n * @type {string}\n */\nconst START = 'start';\n\n/**\n * The recognized phases.\n *\n * @memberof westures-core\n * @type {list.<string>}\n */\nconst PHASES = [START, MOVE, END, CANCEL];\n\n/**\n * Object that normalizes the names of window events to be either of type start,\n * move, end, or cancel.\n *\n * @memberof westures-core\n * @type {object}\n */\nconst PHASE = {\n blur: CANCEL,\n pointercancel: CANCEL,\n touchcancel: CANCEL,\n\n mouseup: END,\n pointerup: END,\n touchend: END,\n\n mousemove: MOVE,\n pointermove: MOVE,\n touchmove: MOVE,\n\n mousedown: START,\n pointerdown: START,\n touchstart: START,\n};\n\nmodule.exports = {\n CANCEL_EVENTS,\n KEYBOARD_EVENTS,\n MOUSE_EVENTS,\n POINTER_EVENTS,\n TOUCH_EVENTS,\n\n STATE_KEYS,\n STATE_KEY_STRINGS,\n\n CANCEL,\n END,\n MOVE,\n START,\n\n PHASE,\n PHASES,\n};\n\n","'use strict';\n\nconst PI_2 = 2 * Math.PI;\nconst PI_NVE = -Math.PI;\n\n/**\n * Helper function to regulate angular differences, so they don't jump from 0 to\n * 2 * PI or vice versa.\n *\n * @memberof westures-core\n *\n * @param {number} a - Angle in radians.\n * @param {number} b - Angle in radians.\n\n * @return {number} c, given by: c = a - b such that |c| < PI\n */\nfunction angularDifference(a, b) {\n let diff = a - b;\n if (diff < PI_NVE) {\n diff += PI_2;\n } else if (diff > Math.PI) {\n diff -= PI_2;\n }\n return diff;\n}\n\n/**\n * In case event.composedPath() is not available.\n *\n * @memberof westures-core\n *\n * @param {Event} event\n *\n * @return {Element[]} The elements along the composed path of the event.\n */\nfunction getPropagationPath(event) {\n if (typeof event.composedPath === 'function') {\n return event.composedPath();\n }\n\n const path = [];\n for (let node = event.target; node !== document; node = node.parentNode) {\n path.push(node);\n }\n path.push(document);\n path.push(window);\n\n return path;\n}\n\n/**\n * Performs a set filter operation.\n *\n * @memberof westures-core\n *\n * @param {Set} set - The set to filter.\n * @param {Function} predicate - Function to test elements of 'set'. Receives\n * one argument: the current set element.\n *\n * @return {Set} Set consisting of elements in 'set' for which 'predicate' is\n * true.\n */\nfunction setFilter(set, predicate) {\n const result = new Set();\n set.forEach(element => {\n if (predicate(element)) {\n result.add(element);\n }\n });\n return result;\n}\n\n/**\n * Performs a set difference operation.\n *\n * @memberof westures-core\n *\n * @param {Set} left - Base set.\n * @param {Set} right - Set of elements to remove from 'left'.\n *\n * @return {Set} Set consisting of elements in 'left' that are not in\n * 'right'.\n */\nfunction setDifference(left, right) {\n return setFilter(left, element => !right.has(element));\n}\n\nmodule.exports = {\n angularDifference,\n getPropagationPath,\n setDifference,\n setFilter,\n};\n\n","'use strict';\n\nconst State = require('./State.js');\nconst {\n CANCEL_EVENTS,\n KEYBOARD_EVENTS,\n MOUSE_EVENTS,\n POINTER_EVENTS,\n TOUCH_EVENTS,\n\n STATE_KEY_STRINGS,\n\n PHASE,\n\n CANCEL,\n END,\n START,\n} = require('./constants.js');\nconst {\n setDifference,\n setFilter,\n} = require('./utils.js');\n\n/**\n * Allows the user to specify the control region which will listen for user\n * input events.\n *\n * @memberof westures-core\n *\n * @param {Element} [element=null] - The element which should listen to input\n * events. If not provided, will be set to the window unless operating in\n * \"headless\" mode.\n * @param {object} [options]\n * @param {boolean} [options.capture=false] - Whether the region uses the\n * capture phase of input events. If false, uses the bubbling phase.\n * @param {boolean} [options.preferPointer=true] - If false, the region listens\n * to mouse/touch events instead of pointer events.\n * @param {boolean} [options.preventDefault=true] - Whether the default\n * browser functionality should be disabled. This option should most likely be\n * ignored. Here there by dragons if set to false.\n * @param {string} [options.touchAction='none'] - Value to set the CSS\n * 'touch-action' property to on elements added to the region.\n * @param {boolean} [options.headless=false] - Set to true to turn on \"headless\"\n * mode. This mode is intended for use outside of a browser environment. It does\n * not listen to window events, so instead you will have to send events directly\n * into the region. Pointer down/move/up events should be sent to\n * Region.arbitrate(event), cancel events should be sent to\n * Region.cancel(event), and keyboard events should be sent to\n * Region.handleKeyboardEvent(event). You do not need to supply an element to\n * the Region constructor in this mode, but you will still need to attach\n * elements to Gestures, and the events you pass in should specify event.target\n * appropriately, in order to select which gestures to run.\n */\nclass Region {\n constructor(element = null, options = {}) {\n options = { ...Region.DEFAULTS, ...options };\n if (element === null) {\n if (options.headless) {\n element = null;\n } else {\n element = window;\n }\n }\n\n /**\n * The list of relations between elements, their gestures, and the handlers.\n *\n * @type {Set.<westures-core.Gesture>}\n */\n this.gestures = new Set();\n\n /**\n * The list of active gestures for the current input session.\n *\n * @type {Set.<westures-core.Gesture>}\n */\n this.activeGestures = new Set();\n\n /**\n * The base list of potentially active gestures for the current input\n * session.\n *\n * @type {Set.<westures-core.Gesture>}\n */\n this.potentialGestures = new Set();\n\n /**\n * The element being bound to.\n *\n * @type {Element}\n */\n this.element = element;\n\n /**\n * The user-supplied options for the Region.\n *\n * @type {object}\n */\n this.options = options;\n\n /**\n * The internal state object for a Region. Keeps track of inputs.\n *\n * @type {westures-core.State}\n */\n this.state = new State(this.element, options.headless);\n\n if (!options.headless) {\n // Begin operating immediately.\n this.activate();\n }\n }\n\n /**\n * Activates the region by adding event listeners for all appropriate input\n * events to the region's element.\n *\n * @private\n */\n activate() {\n /*\n * Listening to both mouse and touch comes with the difficulty that\n * preventDefault() must be called to prevent both events from iterating\n * through the system. However I have left it as an option to the end user,\n * which defaults to calling preventDefault(), in case there's a use-case I\n * haven't considered or am not aware of.\n *\n * It also may be a good idea to keep regions small in large pages.\n *\n * See:\n * https://www.html5rocks.com/en/mobile/touchandmouse/\n * https://developer.mozilla.org/en-US/docs/Web/API/Touch_events\n * https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events\n */\n const eventNames = this.options.preferPointer && window.PointerEvent\n ? POINTER_EVENTS\n : MOUSE_EVENTS.concat(TOUCH_EVENTS);\n\n // Bind detected browser events to the region element.\n const arbitrate = this.arbitrate.bind(this);\n eventNames.forEach(eventName => {\n this.element.addEventListener(eventName, arbitrate, {\n capture: this.options.capture,\n once: false,\n passive: false,\n });\n });\n\n const cancel = this.cancel.bind(this);\n CANCEL_EVENTS.forEach(eventName => {\n window.addEventListener(eventName, cancel);\n });\n\n const handleKeyboardEvent = this.handleKeyboardEvent.bind(this);\n KEYBOARD_EVENTS.forEach(eventName => {\n window.addEventListener(eventName, handleKeyboardEvent);\n });\n }\n\n /**\n * Handles a cancel event. Resets the state and the active / potential gesture\n * lists.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n */\n cancel(event) {\n if (\n this.options.preventDefault && typeof event.preventDefault === 'function'\n ) {\n event.preventDefault();\n }\n this.state.inputs.forEach(input => {\n input.update(event);\n });\n this.activeGestures.forEach(gesture => {\n gesture.evaluateHook(CANCEL, this.state);\n });\n this.state = new State(this.element, this.options.headless);\n this.resetActiveGestures();\n }\n\n /**\n * Handles a keyboard event, triggering a restart of any gestures that need\n * it.\n *\n * @private\n * @param {KeyboardEvent} event - The keyboard event.\n */\n handleKeyboardEvent(event) {\n if (STATE_KEY_STRINGS.indexOf(event.key) >= 0) {\n this.state.event = event;\n const oldActiveGestures = this.activeGestures;\n this.setActiveGestures();\n\n setDifference(oldActiveGestures, this.activeGestures).forEach(gesture => {\n gesture.evaluateHook(END, this.state);\n });\n setDifference(this.activeGestures, oldActiveGestures).forEach(gesture => {\n gesture.evaluateHook(START, this.state);\n });\n }\n }\n\n /**\n * Resets the active gestures.\n *\n * @private\n */\n resetActiveGestures() {\n this.potentialGestures = new Set();\n this.activeGestures = new Set();\n }\n\n /**\n * Selects active gestures from the list of potentially active gestures.\n *\n * @private\n */\n setActiveGestures() {\n this.activeGestures = setFilter(this.potentialGestures, gesture => {\n return gesture.isEnabled(this.state);\n });\n }\n\n /**\n * Selects the potentially active gestures.\n *\n * @private\n */\n setPotentialGestures() {\n const input = this.state.inputs[0];\n this.potentialGestures = setFilter(this.gestures, gesture => {\n return input.initialElements.has(gesture.element);\n });\n }\n\n /**\n * Selects the gestures that are active for the current input sequence.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n * @param {boolean} isInitial - Whether this is an initial contact.\n */\n updateActiveGestures(event, isInitial) {\n if (PHASE[event.type] === START) {\n if (isInitial) {\n this.setPotentialGestures();\n }\n this.setActiveGestures();\n }\n }\n\n /**\n * Evaluates whether the current input session has completed.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n */\n pruneActiveGestures(event) {\n if (PHASE[event.type] === END) {\n if (this.state.hasNoInputs()) {\n this.resetActiveGestures();\n } else {\n this.setActiveGestures();\n }\n }\n }\n\n /**\n * All input events flow through this function. It makes sure that the input\n * state is maintained, determines which gestures to analyze based on the\n * initial position of the inputs, calls the relevant gesture hooks, and\n * dispatches gesture data.\n *\n * @private\n * @param {Event} event - The event emitted from the window object.\n */\n arbitrate(event) {\n const isInitial = this.state.hasNoInputs();\n this.state.updateAllInputs(event);\n this.updateActiveGestures(event, isInitial);\n\n if (this.activeGestures.size > 0) {\n if (\n this.options.preventDefault &&\n typeof event.preventDefault === 'function'\n ) event.preventDefault();\n\n this.activeGestures.forEach(gesture => {\n gesture.evaluateHook(PHASE[event.type], this.state);\n });\n }\n\n this.state.clearEndedInputs();\n this.pruneActiveGestures(event);\n }\n\n /**\n * Adds the given gesture to the region.\n *\n * @param {westures-core.Gesture} gesture - Instantiated gesture to add.\n */\n addGesture(gesture) {\n if (!this.options.headless) {\n gesture.element.style.touchAction = this.options.touchAction;\n }\n this.gestures.add(gesture);\n }\n\n /**\n * Removes the given gesture from the region.\n *\n * @param {westures-core.Gesture} gesture - Instantiated gesture to add.\n */\n removeGesture(gesture) {\n this.gestures.delete(gesture);\n this.potentialGestures.delete(gesture);\n this.activeGestures.delete(gesture);\n }\n\n /**\n * Retrieves Gestures by their associated element.\n *\n * @param {Element} element - The element for which to find gestures.\n *\n * @return {westures-core.Gesture[]} Gestures to which the element is bound.\n */\n getGesturesByElement(element) {\n return setFilter(this.gestures, gesture => gesture.element === element);\n }\n\n /**\n * Remove all gestures bound to the given element.\n *\n * @param {Element} element - The element to unbind.\n */\n removeGesturesByElement(element) {\n this.getGesturesByElement(element).forEach(g => this.removeGesture(g));\n }\n}\n\nRegion.DEFAULTS = {\n capture: false,\n preferPointer: true,\n preventDefault: true,\n touchAction: 'none',\n headless: false,\n};\n\nmodule.exports = Region;\n","'use strict';\n\nconst {\n CANCEL,\n END,\n MOVE,\n PHASE,\n START,\n MOUSE_EVENTS,\n POINTER_EVENTS,\n TOUCH_EVENTS,\n} = require('./constants.js');\nconst Input = require('./Input.js');\nconst Point2D = require('./Point2D.js');\n\nconst symbols = {\n inputs: Symbol.for('inputs'),\n};\n\n/**\n * Keeps track of currently active and ending input points on the interactive\n * surface.\n *\n * @memberof westures-core\n *\n * @param {Element} element - The element underpinning the associated Region.\n * @param {boolean} [headless=false] - Whether westures is operating in\n * \"headless\" mode.\n */\nclass State {\n constructor(element, headless = false) {\n /**\n * Keep a reference to the element for the associated region.\n *\n * @type {Element}\n */\n this.element = element;\n\n /**\n * Whether westures is operating in \"headless\" mode.\n *\n * @type {boolean}\n */\n this.headless = headless;\n\n /**\n * Keeps track of the current Input objects.\n *\n * @alias [@@inputs]\n * @type {Map.<westures-core.Input>}\n * @memberof westure-core.State\n */\n this[symbols.inputs] = new Map();\n\n /**\n * All currently valid inputs, including those that have ended.\n *\n * @type {westures-core.Input[]}\n */\n this.inputs = [];\n\n /**\n * The array of currently active inputs, sourced from the current Input\n * objects. \"Active\" is defined as not being in the 'end' phase.\n *\n * @type {westures-core.Input[]}\n */\n this.active = [];\n\n /**\n * The array of latest point data for the currently active inputs, sourced\n * from this.active.\n *\n * @type {westures-core.Point2D[]}\n */\n this.activePoints = [];\n\n /**\n * The centroid of the currently active points, or null when there are no\n * active inputs (such as during the final end event).\n *\n * @type {?westures-core.Point2D}\n */\n this.centroid = null;\n\n /**\n * The latest event that the state processed.\n *\n * @type {Event}\n */\n this.event = null;\n }\n\n /**\n * Deletes all inputs that are in the 'end' phase.\n */\n clearEndedInputs() {\n this[symbols.inputs].forEach((v, k) => {\n if (v.phase === 'end') this[symbols.inputs].delete(k);\n });\n }\n\n /**\n * @param {string} phase - One of 'start', 'move', 'end', or 'cancel'.\n *\n * @return {westures-core.Input[]} Inputs in the given phase.\n */\n getInputsInPhase(phase) {\n return this.inputs.filter(i => i.phase === phase);\n }\n\n /**\n * @param {string} phase - One of 'start', 'move', 'end', or 'cancel'.\n *\n * @return {westures-core.Input[]} Inputs <b>not</b> in the given phase.\n */\n getInputsNotInPhase(phase) {\n return this.inputs.filter(i => i.phase !== phase);\n }\n\n /**\n * @return {boolean} True if there are no active inputs. False otherwise.\n */\n hasNoInputs() {\n return this[symbols.inputs].size === 0;\n }\n\n /**\n * Update the input with the given identifier using the given event.\n *\n * @private\n *\n * @param {Event} event - The event being captured.\n * @param {number} identifier - The identifier of the input to update.\n */\n updateInput(event, identifier) {\n switch (PHASE[event.type]) {\n case START:\n this[symbols.inputs].set(\n identifier,\n new Input(event, identifier, this.headless),\n );\n if (!this.headless) {\n try {\n this.element.setPointerCapture(identifier);\n } catch (e) { // eslint-disable-line\n // NOP: Optional operation failed.\n }\n }\n break;\n\n // All of 'end', 'move', and 'cancel' perform updates, hence the\n // following fall-throughs\n case END:\n if (!this.headless) {\n try {\n this.element.releasePointerCapture(identifier);\n } catch (e) { // eslint-disable-line\n // NOP: Optional operation failed.\n }\n }\n case CANCEL:\n case MOVE:\n if (this[symbols.inputs].has(identifier)) {\n this[symbols.inputs].get(identifier).update(event);\n }\n break;\n\n default:\n console.warn(`Unrecognized event type: ${event.type}`);\n }\n }\n\n /**\n * Updates the inputs with new information based upon a new event being fired.\n *\n * @private\n * @param {Event} event - The event being captured.\n */\n updateAllInputs(event) {\n if (POINTER_EVENTS.includes(event.type)) {\n this.updateInput(event, event.pointerId);\n } else if (MOUSE_EVENTS.includes(event.type)) {\n if (event.button === 0) {\n this.updateInput(event, event.button);\n }\n } else if (TOUCH_EVENTS.includes(event.type)) {\n Array.from(event.changedTouches).forEach(touch => {\n this.updateInput(event, touch.identifier);\n });\n } else {\n throw new Error(`Unexpected event type: ${event.type}`);\n }\n this.updateFields(event);\n }\n\n /**\n * Updates the convenience fields.\n *\n * @private\n * @param {Event} event - Event with which to update the convenience fields.\n */\n updateFields(event) {\n this.inputs = Array.from(this[symbols.inputs].values());\n this.active = this.getInputsNotInPhase('end');\n this.activePoints = this.active.map(i => i.current.point);\n this.centroid = Point2D.centroid(this.activePoints);\n this.event = event;\n }\n}\n\nmodule.exports = State;\n","'use strict';\n\nconst cascade = Symbol('cascade');\nconst smooth = Symbol('smooth');\n\n/**\n * Determines whether to apply smoothing. Smoothing is on by default but turned\n * off if either:<br>\n * 1. The user explicitly requests that it be turned off.<br>\n * 2. The active pointer is not \"coarse\".<br>\n *\n * @see {@link\n * https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia}\n *\n * @inner\n * @memberof westures-core.Smoothable\n *\n * @param {boolean} isRequested - Whether smoothing was requested by the user.\n *\n * @returns {boolean} Whether to apply smoothing.\n */\nfunction smoothingIsApplicable(isRequested) {\n if (isRequested) {\n try {\n return window.matchMedia('(pointer: coarse)').matches;\n } catch (e) { // eslint-disable-line\n return true;\n }\n }\n return false;\n}\n\n/**\n * A Smoothable datatype is one that is capable of smoothing out a series of\n * values as they come in, one at a time, providing a more consistent series. It\n * does this by creating some inertia in the values using a cascading average.\n * (For those who are interested in such things, this effectively means that it\n * provides a practical application of Zeno's Dichotomy).\n *\n * @example\n * const x = new Smoothable({ identity: 1 });\n * const a = x.next(1); // 1.0\n * const b = x.next(1.2); // 1.1\n * const c = x.next(0.9); // 1.0\n * const d = x.next(0.6); // 0.8\n * const e = x.next(1.2); // 1.0\n * const f = x.next(1.6); // 1.3\n * x.restart();\n * const g = x.next(0); // 0.5\n *\n * @memberof westures-core\n *\n * @param {Object} [options]\n * @param {boolean} [options.applySmoothing=true] Whether to apply smoothing to\n * the data.\n * @param {*} [options.identity=0] The identity value of this smoothable data.\n */\nclass Smoothable {\n constructor(options = {}) {\n const final_options = { ...Smoothable.DEFAULTS, ...options };\n\n /**\n * The function through which smoothed emits are passed.\n *\n * @method\n * @param {*} data - The data to emit.\n *\n * @return {*} The smoothed out data.\n */\n this.next = null;\n if (smoothingIsApplicable(final_options.applySmoothing)) {\n this.next = this[smooth].bind(this);\n } else {\n this.next = data => data;\n }\n\n /**\n * The \"identity\" value of the data that will be smoothed.\n *\n * @type {*}\n * @default 0\n */\n this.identity = final_options.identity;\n\n /**\n * The cascading average of outgoing values.\n *\n * @memberof westures-core.Smoothable\n * @alias [@@cascade]\n * @type {object}\n */\n this[cascade] = this.identity;\n }\n\n /**\n * Restart the Smoothable gesture.\n */\n restart() {\n this[cascade] = this.identity;\n }\n\n /**\n * Smooth out the outgoing data.\n *\n * @memberof westures-core.Smoothable\n * @alias [@@smooth]\n * @param {object} data - The next batch of data to emit.\n *\n * @return {?object}\n */\n [smooth](data) {\n const average = this.average(this[cascade], data);\n this[cascade] = average;\n return average;\n }\n\n /**\n * Average out two values, as part of the smoothing algorithm. Override this\n * method if the data being smoothed is not a Number.\n *\n * @param {number} a\n * @param {number} b\n *\n * @return {number} The average of 'a' and 'b'\n */\n average(a, b) {\n return (a + b) / 2;\n }\n}\n\nSmoothable.DEFAULTS = {\n applySmoothing: true,\n identity: 0,\n};\n\nmodule.exports = Smoothable;\n\n"],"names":[],"version":3,"file":"index.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "westures-core",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "The core engine of Westures, a robust n-pointer multitouch gesture detection library for JavaScript.",
5
5
  "author": "Michael van der Kamp <michael.vanderkamp@usask.ca>",
6
6
  "keywords": [
@@ -35,11 +35,12 @@
35
35
  "scripts": {
36
36
  "build": "parcel build",
37
37
  "build:debug": "parcel build --no-optimize",
38
- "coveralls": "jest --coverage && cat ./coverage/lcov.info | coveralls",
39
38
  "docs": "jsdoc -c .jsdocrc.json",
40
39
  "lint": "eslint src test index.js",
41
40
  "lint:fix": "eslint --fix src test index.js",
41
+ "prepare": "npm run build",
42
42
  "test": "jest",
43
+ "test:coverage": "jest --coverage",
43
44
  "test:debug": "node inspect $(npm bin)/jest --runInBand"
44
45
  },
45
46
  "jest": {
@@ -66,14 +67,14 @@
66
67
  }
67
68
  },
68
69
  "devDependencies": {
69
- "@babel/core": "^7.21.8",
70
- "@babel/preset-env": "^7.21.5",
71
- "docdash": "^2.0.1",
72
- "eslint": "^8.41.0",
73
- "jest": "^29.5.0",
74
- "jest-environment-jsdom": "^29.5.0",
75
- "jsdoc": "^4.0.2",
76
- "parcel": "^2.8.3",
77
- "underscore": "^1.13.6"
70
+ "@eslint/js": "^10.0.1",
71
+ "docdash": "^2.0.2",
72
+ "eslint": "^10.8.1",
73
+ "globals": "^17.11.0",
74
+ "jest": "^30.3.0",
75
+ "jest-environment-jsdom": "^30.3.0",
76
+ "jsdoc": "^4.0.3",
77
+ "parcel": "^2.12.0",
78
+ "underscore": "^1.13.7"
78
79
  }
79
80
  }
package/src/Region.js CHANGED
@@ -132,12 +132,9 @@ class Region {
132
132
  * https://developer.mozilla.org/en-US/docs/Web/API/Touch_events
133
133
  * https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events
134
134
  */
135
- let eventNames = [];
136
- if (this.options.preferPointer && window.PointerEvent) {
137
- eventNames = POINTER_EVENTS;
138
- } else {
139
- eventNames = MOUSE_EVENTS.concat(TOUCH_EVENTS);
140
- }
135
+ const eventNames = this.options.preferPointer && window.PointerEvent
136
+ ? POINTER_EVENTS
137
+ : MOUSE_EVENTS.concat(TOUCH_EVENTS);
141
138
 
142
139
  // Bind detected browser events to the region element.
143
140
  const arbitrate = this.arbitrate.bind(this);
package/src/Smoothable.js CHANGED
@@ -23,7 +23,7 @@ function smoothingIsApplicable(isRequested) {
23
23
  if (isRequested) {
24
24
  try {
25
25
  return window.matchMedia('(pointer: coarse)').matches;
26
- } catch (e) {
26
+ } catch (e) { // eslint-disable-line
27
27
  return true;
28
28
  }
29
29
  }
package/src/State.js CHANGED
@@ -76,11 +76,12 @@ class State {
76
76
  this.activePoints = [];
77
77
 
78
78
  /**
79
- * The centroid of the currently active points.
79
+ * The centroid of the currently active points, or null when there are no
80
+ * active inputs (such as during the final end event).
80
81
  *
81
- * @type {westures-core.Point2D}
82
+ * @type {?westures-core.Point2D}
82
83
  */
83
- this.centroid = {};
84
+ this.centroid = null;
84
85
 
85
86
  /**
86
87
  * The latest event that the state processed.
@@ -142,7 +143,7 @@ class State {
142
143
  if (!this.headless) {
143
144
  try {
144
145
  this.element.setPointerCapture(identifier);
145
- } catch (e) {
146
+ } catch (e) { // eslint-disable-line
146
147
  // NOP: Optional operation failed.
147
148
  }
148
149
  }
@@ -154,7 +155,7 @@ class State {
154
155
  if (!this.headless) {
155
156
  try {
156
157
  this.element.releasePointerCapture(identifier);
157
- } catch (e) {
158
+ } catch (e) { // eslint-disable-line
158
159
  // NOP: Optional operation failed.
159
160
  }
160
161
  }
@@ -209,4 +210,3 @@ class State {
209
210
  }
210
211
 
211
212
  module.exports = State;
212
-
package/src/constants.js CHANGED
@@ -8,6 +8,7 @@
8
8
  */
9
9
  const CANCEL_EVENTS = [
10
10
  'blur',
11
+ 'contextmenu',
11
12
  'pointercancel',
12
13
  'touchcancel',
13
14
  'mouseleave',