All files / widgets track-gesture.ts

95% Statements 19/20
100% Branches 2/2
100% Functions 5/5
94.73% Lines 18/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174        94x   94x   94x   94x                                                                                           94x   8x 8x 4x   4x       94x     3x 3x                 5x   5x                   5x                                                                                                                                     94x     94x     94x                  
/**
 * @module Widgets
 */
 
import * as MH from "@lisn/globals/minification-helpers";
 
import { validateBoolean, validateNumber } from "@lisn/utils/validation";
 
import { GestureWatcher } from "@lisn/watchers/gesture-watcher";
 
import {
  Widget,
  WidgetConfigValidatorObject,
  registerWidget,
} from "@lisn/widgets/widget";
 
/**
 * This is a simple wrapper around the {@link GestureWatcher}. If you are using
 * the JavaScript API, you should use the {@link GestureWatcher} directly. The
 * purpose of this widget is to expose the watcher's ability to track gestures
 * and set relevant CSS properties via the HTML API. See
 * {@link GestureWatcher.trackGesture}.
 *
 * -----
 *
 * To use with auto-widgets (HTML API) (see
 * {@link Settings.settings.autoWidgets | settings.autoWidgets}), the following
 * CSS classes or data attributes are recognized:
 * - `lisn-track-gesture` class or `data-lisn-track-gesture` attribute set on
 *   the element that constitutes the widget.
 *
 * See below examples for what values you can use set for the data attributes
 * in order to modify the configuration of the automatically created widget.
 *
 * @example
 * This will track user gestures over this element and set the relevant CSS
 * properties. It will use the default {@link GestureWatcher} options.
 *
 * ```html
 * <div class="lisn-track-gesture"></div>
 * ```
 *
 * @example
 * As above but with custom settings.
 *
 * ```html
 * <div data-lisn-track-gesture="prevent-default=false
 *                               | min-delta-x=-100
 *                               | max-delta-x=100
 *                               | min-delta-y=-100
 *                               | max-delta-y=100
 *                               | min-delta-z=0.5
 *                               | max-delta-z=2"
 * ></div>
 * ```
 */
export class TrackGesture extends Widget {
  static get(element: Element): TrackGesture | null {
    const instance = super.get(element, DUMMY_ID);
    if (MH.isInstanceOf(instance, TrackGesture)) {
      return instance;
    }
    return null;
  }
 
  static register() {
    registerWidget(
      WIDGET_NAME,
      (element, config) => {
        if (!TrackGesture.get(element)) {
          return new TrackGesture(element, config);
        }
        return null;
      },
      configValidator,
    );
  }
 
  constructor(element: Element, config?: TrackGestureConfig) {
    super(element, { id: DUMMY_ID });
 
    GestureWatcher.reuse().trackGesture(element, null, {
      preventDefault: config?.preventDefault,
      minTotalDeltaX: config?.minDeltaX,
      maxTotalDeltaX: config?.maxDeltaX,
      minTotalDeltaY: config?.minDeltaY,
      maxTotalDeltaY: config?.maxDeltaY,
      minTotalDeltaZ: config?.minDeltaZ,
      maxTotalDeltaZ: config?.maxDeltaZ,
    });
 
    this.onDestroy(() => GestureWatcher.reuse().noTrackGesture(element));
  }
}
 
/**
 * @interface
 */
export type TrackGestureConfig = {
  /**
   * Corresponds to
   * {@link Watchers/GestureWatcher.OnGestureOptions.preventDefault | OnGestureOptions.preventDefault}.
   *
   * @defaultValue undefined // GestureWatcher default
   */
  preventDefault?: boolean;
 
  /**
   * Corresponds to
   * {@link Watchers/GestureWatcher.OnGestureOptions.minTotalDeltaX | OnGestureOptions.minTotalDeltaX}.
   *
   * @defaultValue undefined // GestureWatcher default
   */
  minDeltaX?: number;
 
  /**
   * Corresponds to
   * {@link Watchers/GestureWatcher.OnGestureOptions.maxTotalDeltaX | OnGestureOptions.maxTotalDeltaX}.
   *
   * @defaultValue undefined // GestureWatcher default
   */
  maxDeltaX?: number;
 
  /**
   * Corresponds to
   * {@link Watchers/GestureWatcher.OnGestureOptions.minTotalDeltaY | OnGestureOptions.minTotalDeltaY}.
   *
   * @defaultValue undefined // GestureWatcher default
   */
  minDeltaY?: number;
 
  /**
   * Corresponds to
   * {@link Watchers/GestureWatcher.OnGestureOptions.maxTotalDeltaY | OnGestureOptions.maxTotalDeltaY}.
   *
   * @defaultValue undefined // GestureWatcher default
   */
  maxDeltaY?: number;
 
  /**
   * Corresponds to
   * {@link Watchers/GestureWatcher.OnGestureOptions.minTotalDeltaZ | OnGestureOptions.minTotalDeltaZ}.
   *
   * @defaultValue undefined // GestureWatcher default
   */
  minDeltaZ?: number;
 
  /**
   * Corresponds to
   * {@link Watchers/GestureWatcher.OnGestureOptions.maxTotalDeltaZ | OnGestureOptions.maxTotalDeltaZ}.
   *
   * @defaultValue undefined // GestureWatcher default
   */
  maxDeltaZ?: number;
};
 
// --------------------
 
const WIDGET_NAME = "track-gesture";
// Only one TrackGesture widget per element is allowed, but Widget requires a
// non-blank ID.
const DUMMY_ID = WIDGET_NAME;
 
// For HTML API only
const configValidator: WidgetConfigValidatorObject<TrackGestureConfig> = {
  preventDefault: validateBoolean,
  minDeltaX: validateNumber,
  maxDeltaX: validateNumber,
  minDeltaY: validateNumber,
  maxDeltaY: validateNumber,
  minDeltaZ: validateNumber,
  maxDeltaZ: validateNumber,
};