text: define(function(require) {
      'use strict';
  
      const _ = require('underscore');
      const mediator = require('oroui/js/mediator');
      const BaseView = require('oroui/js/app/views/base/view');
  
      const SwipeableView = BaseView.extend({
          optionNames: BaseView.prototype.optionNames.concat(['minDistanceXAxis', 'maxDistanceYAxis', 'maxAllowedTime']),
  
          /** @type {string} */
          direction: void 0,
  
          /** @type {{x: Number, y: Number}|null} */
          touchStartCoords: null,
  
          /** @type {{x: Number, y: Number}|null} */
          touchEndCoords: null,
  
          /** @type {Number} */
          elapsedTime: 0,
  
          /** @type {Number} */
          startTime: 0,
  
          minDistanceXAxis: 30,
  
          maxDistanceYAxis: 30,
  
          maxAllowedTime: 1000,
  
          events: {
              touchstart: '_swipeStart',
              touchmove: '_swipeMove',
              touchend: '_swipeEnd'
          },
  
          /**
           * Swipe actions on mobile devices
           *
           * @inheritdoc
           */
          constructor: function SwipeableView(options) {
              SwipeableView.__super__.constructor.call(this, options);
          },
  
          /**
           * Handler for start touch
           *
           * @param {jQuery.Event} event
           * @private
           */
          _swipeStart: function(event) {
              event = ('changedTouches' in event) ? event.changedTouches[0] : event;
  
              this.touchStartCoords = {
                  x: event.pageX,
                  y: event.pageY
              };
  
              this.startTime = new Date().getTime();
  
              mediator.trigger('swipe-action-start', {}, event.target);
          },
  
          /**
           * Handler for start move
           *
           * @param {jQuery.Event} event
           * @private
           */
          _swipeMove: function(event) {
              if (!this.touchStartCoords) {
                  return;
              }
  
              event = ('changedTouches' in event) ? event.changedTouches[0] : event;
  
              const touchEndCoords = {
                  x: event.pageX - this.touchStartCoords.x,
                  y: event.pageY - this.touchStartCoords.y
              };
  
              mediator.trigger('swipe-action-move', this._collectOptions(touchEndCoords), event.target);
          },
  
          /**
           * Handler for end touch and fire external mediator event
           *
           * @param {jQuery.Event} event
           * @private
           */
          _swipeEnd: function(event) {
              if (!this.touchStartCoords) {
                  return;
              }
  
              event = ('changedTouches' in event) ? event.changedTouches[0] : event;
  
              this.touchEndCoords = {
                  x: event.pageX - this.touchStartCoords.x,
                  y: event.pageY - this.touchStartCoords.y
              };
              this.elapsedTime = new Date().getTime() - this.startTime;
  
              if (this.elapsedTime <= this.maxAllowedTime) {
                  if (
                      Math.abs(this.touchEndCoords.x) >= this.minDistanceXAxis &&
                      Math.abs(this.touchEndCoords.y) <= this.maxDistanceYAxis
                  ) {
                      this.direction = this._getDirection(this.touchEndCoords.x);
                      mediator.trigger('swipe-action-' + this.direction, this.touchEndCoords, event.target, event);
                  }
              }
  
              mediator.trigger('swipe-action-end', this._collectOptions(this.touchEndCoords), event.target);
          },
  
          _getDirection: function(coords) {
              return (coords < 0) ? 'left' : 'right';
          },
  
          _collectOptions: function(options) {
              return _.extend({}, options, {
                  direction: this._getDirection(options.x)
              });
          }
      });
  
      return SwipeableView;
  });
  