text: import { Component, ElementRef, EventEmitter, Input, HostListener, NgZone, Output, Renderer, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
  import { DomSanitizer } from '@angular/platform-browser';
  import { CSS, cancelRaf, pointerCoord, nativeRaf } from '../../util/dom';
  import { clamp, isNumber, isPresent, isString } from '../../util/util';
  import { Config } from '../../config/config';
  import { Key } from '../../util/key';
  import { NavParams } from '../../navigation/nav-params';
  import { Haptic } from '../../util/haptic';
  import { UIEventManager } from '../../util/ui-event-manager';
  import { ViewController } from '../../navigation/view-controller';
  import { NativeRafDebouncer } from '../../util/debouncer';
  import { GestureController, BLOCK_ALL } from '../../gestures/gesture-controller';
  export class PickerColumnCmp {
      constructor(config, elementRef, _sanitizer, _zone, _haptic) {
          this.elementRef = elementRef;
          this._sanitizer = _sanitizer;
          this._zone = _zone;
          this._haptic = _haptic;
          this.y = 0;
          this.pos = [];
          this.startY = null;
          this.debouncer = new NativeRafDebouncer();
          this.events = new UIEventManager(false);
          this.ionChange = new EventEmitter();
          this.rotateFactor = config.getNumber('pickerRotateFactor', 0);
          this.scaleFactor = config.getNumber('pickerScaleFactor', 1);
          this.decelerateFunc = this.decelerate.bind(this);
      }
      ngAfterViewInit() {
          let colEle = this.colEle.nativeElement;
          this.colHeight = colEle.clientHeight;
          this.optHeight = (colEle.firstElementChild ? colEle.firstElementChild.clientHeight : 0);
          this.setSelected(this.col.selectedIndex, 0);
          this.events.pointerEvents({
              elementRef: this.elementRef,
              pointerDown: this.pointerStart.bind(this),
              pointerMove: this.pointerMove.bind(this),
              pointerUp: this.pointerEnd.bind(this),
              capture: true
          });
      }
      ngOnDestroy() {
          this.events.unlistenAll();
      }
      pointerStart(ev) {
          (void 0);
          this._haptic.gestureSelectionStart();
          ev.preventDefault();
          if (this.rafId) {
              cancelRaf(this.rafId);
              this.rafId = null;
          }
          this.startY = pointerCoord(ev).y;
          this.velocity = 0;
          this.pos.length = 0;
          this.pos.push(this.startY, Date.now());
          let options = this.col.options;
          let minY = (options.length - 1);
          let maxY = 0;
          for (var i = 0; i < options.length; i++) {
              if (!options[i].disabled) {
                  minY = Math.min(minY, i);
                  maxY = Math.max(maxY, i);
              }
          }
          this.minY = (minY * this.optHeight * -1);
          this.maxY = (maxY * this.optHeight * -1);
          return true;
      }
      pointerMove(ev) {
          ev.preventDefault();
          ev.stopPropagation();
          let currentY = pointerCoord(ev).y;
          this.pos.push(currentY, Date.now());
          this.debouncer.debounce(() => {
              if (this.startY === null) {
                  return;
              }
              let y = this.y + (currentY - this.startY);
              if (y > this.minY) {
                  y = Math.pow(y, 0.8);
                  this.bounceFrom = y;
              }
              else if (y < this.maxY) {
                  y += Math.pow(this.maxY - y, 0.9);
                  this.bounceFrom = y;
              }
              else {
                  this.bounceFrom = 0;
              }
              this.update(y, 0, false, false);
              let currentIndex = Math.max(Math.abs(Math.round(y / this.optHeight)), 0);
              if (currentIndex !== this.lastTempIndex) {
                  this._haptic.gestureSelectionChanged();
                  this.lastTempIndex = currentIndex;
              }
          });
      }
      pointerEnd(ev) {
          ev.preventDefault();
          this.debouncer.cancel();
          if (this.startY === null) {
              return;
          }
          (void 0);
          this.velocity = 0;
          if (this.bounceFrom > 0) {
              this.update(this.minY, 100, true, true);
              return;
          }
          else if (this.bounceFrom < 0) {
              this.update(this.maxY, 100, true, true);
              return;
          }
          let endY = pointerCoord(ev).y;
          this.pos.push(endY, Date.now());
          let endPos = (this.pos.length - 1);
          let startPos = endPos;
          let timeRange = (Date.now() - 100);
          for (var i = endPos; i > 0 && this.pos[i] > timeRange; i -= 2) {
              startPos = i;
          }
          if (startPos !== endPos) {
              var timeOffset = (this.pos[endPos] - this.pos[startPos]);
              var movedTop = (this.pos[startPos - 1] - this.pos[endPos - 1]);
              var velocity = ((movedTop / timeOffset) * FRAME_MS);
              this.velocity = clamp(-MAX_PICKER_SPEED, velocity, MAX_PICKER_SPEED);
          }
          if (Math.abs(endY - this.startY) > 3) {
              var y = this.y + (endY - this.startY);
              this.update(y, 0, true, true);
          }
          this.startY = null;
          this.decelerate();
      }
      decelerate() {
          let y = 0;
          if (isNaN(this.y) || !this.optHeight) {
              this.update(y, 0, true, true);
              this._haptic.gestureSelectionEnd();
          }
          else if (Math.abs(this.velocity) > 0) {
              this.velocity *= DECELERATION_FRICTION;
              this.velocity = (this.velocity > 0)
                  ? Math.max(this.velocity, 1)
                  : Math.min(this.velocity, -1);
              y = Math.round(this.y - this.velocity);
              if (y > this.minY) {
                  y = this.minY;
                  this.velocity = 0;
              }
              else if (y < this.maxY) {
                  y = this.maxY;
                  this.velocity = 0;
              }
              var notLockedIn = (y % this.optHeight !== 0 || Math.abs(this.velocity) > 1);
              this.update(y, 0, true, !notLockedIn);
              if (notLockedIn) {
                  this.rafId = nativeRaf(this.decelerateFunc);
              }
          }
          else if (this.y % this.optHeight !== 0) {
              var currentPos = Math.abs(this.y % this.optHeight);
              this.velocity = (currentPos > (this.optHeight / 2) ? 1 : -1);
              this._haptic.gestureSelectionEnd();
              this.decelerate();
          }
          let currentIndex = Math.max(Math.abs(Math.round(y / this.optHeight)), 0);
          if (currentIndex !== this.lastTempIndex) {
              this._haptic.gestureSelectionChanged();
          }
          this.lastTempIndex = currentIndex;
      }
      optClick(ev, index) {
          if (!this.velocity) {
              ev.preventDefault();
              ev.stopPropagation();
              this.setSelected(index, 150);
          }
      }
      setSelected(selectedIndex, duration) {
          let y = (selectedIndex > -1) ? ((selectedIndex * this.optHeight) * -1) : 0;
          if (this.rafId) {
              cancelRaf(this.rafId);
              this.rafId = null;
          }
          this.velocity = 0;
          this.update(y, duration, true, true);
      }
      update(y, duration, saveY, emitChange) {
          y = Math.round(y);
          let i, button, opt, optOffset, visible, translateX, translateY, translateZ, rotateX, transform, selected;
          const parent = this.colEle.nativeElement;
          const children = parent.children;
          const length = children.length;
          const selectedIndex = this.col.selectedIndex = Math.min(Math.max(Math.round(-y / this.optHeight), 0), length - 1);
          const durationStr = (duration === 0) ? null : duration + 'ms';
          const scaleStr = `scale(${this.scaleFactor})`;
          for (i = 0; i < length; i++) {
              button = children[i];
              opt = this.col.options[i];
              optOffset = (i * this.optHeight) + y;
              visible = true;
              transform = '';
              if (this.rotateFactor !== 0) {
                  rotateX = optOffset * this.rotateFactor;
                  if (Math.abs(rotateX) > 90) {
                      visible = false;
                  }
                  else {
                      translateX = 0;
                      translateY = 0;
                      translateZ = 90;
                      transform = `rotateX(${rotateX}deg) `;
                  }
              }
              else {
                  translateX = 0;
                  translateZ = 0;
                  translateY = optOffset;
                  if (Math.abs(translateY) > 170) {
                      visible = false;
                  }
              }
              selected = selectedIndex === i;
              if (visible) {
                  transform += `translate3d(0px,${translateY}px,${translateZ}px) `;
                  if (this.scaleFactor !== 1 && !selected) {
                      transform += scaleStr;
                  }
              }
              else {
                  transform = 'translate3d(-9999px,0px,0px)';
              }
              if (duration !== opt._dur) {
                  opt._dur = duration;
                  button.style[CSS.transitionDuration] = durationStr;
              }
              if (transform !== opt._trans) {
                  opt._trans = transform;
                  button.style[CSS.transform] = transform;
              }
              if (selected !== opt._selected) {
                  opt._selected = selected;
                  if (selected) {
                      button.classList.add(PICKER_OPT_SELECTED);
                  }
                  else {
                      button.classList.remove(PICKER_OPT_SELECTED);
                  }
              }
          }
          if (saveY) {
              this.y = y;
          }
          if (emitChange) {
              if (this.lastIndex === undefined) {
                  this.lastIndex = this.col.selectedIndex;
              }
              else if (this.lastIndex !== this.col.selectedIndex) {
                  this.lastIndex = this.col.selectedIndex;
                  var ionChange = this.ionChange;
                  if (ionChange.observers.length > 0) {
                      this._zone.run(ionChange.emit.bind(ionChange, this.col.options[this.col.selectedIndex]));
                  }
              }
          }
      }
      refresh() {
          let min = this.col.options.length - 1;
          let max = 0;
          for (var i = 0; i < this.col.options.length; i++) {
              if (!this.col.options[i].disabled) {
                  min = Math.min(min, i);
                  max = Math.max(max, i);
              }
          }
          var selectedIndex = clamp(min, this.col.selectedIndex, max);
          if (selectedIndex !== this.col.selectedIndex) {
              var y = (selectedIndex * this.optHeight) * -1;
              this.update(y, 150, true, true);
          }
      }
  }
  PickerColumnCmp.decorators = [
      { type: Component, args: [{
                  selector: '.picker-col',
                  template: '<div *ngIf="col.prefix" class="picker-prefix" [style.width]="col.prefixWidth">{{col.prefix}}</div>' +
                      '<div class="picker-opts" #colEle [style.max-width]="col.optionsWidth">' +
                      '<button *ngFor="let o of col.options; let i=index"' +
                      '[class.picker-opt-disabled]="o.disabled" ' +
                      'class="picker-opt" disable-activated (click)="optClick($event, i)">' +
                      '{{o.text}}' +
                      '</button>' +
                      '</div>' +
                      '<div *ngIf="col.suffix" class="picker-suffix" [style.width]="col.suffixWidth">{{col.suffix}}</div>',
                  host: {
                      '[style.max-width]': 'col.columnWidth',
                      '[class.picker-opts-left]': 'col.align=="left"',
                      '[class.picker-opts-right]': 'col.align=="right"',
                  }
              },] },
  ];
  PickerColumnCmp.ctorParameters = [
      { type: Config, },
      { type: ElementRef, },
      { type: DomSanitizer, },
      { type: NgZone, },
      { type: Haptic, },
  ];
  PickerColumnCmp.propDecorators = {
      'colEle': [{ type: ViewChild, args: ['colEle',] },],
      'col': [{ type: Input },],
      'ionChange': [{ type: Output },],
  };
  export class PickerCmp {
      constructor(_viewCtrl, _elementRef, _config, gestureCtrl, params, renderer) {
          this._viewCtrl = _viewCtrl;
          this._elementRef = _elementRef;
          this._config = _config;
          this._gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
          this.d = params.data;
          this.mode = _config.get('mode');
          renderer.setElementClass(_elementRef.nativeElement, `picker-${this.mode}`, true);
          if (this.d.cssClass) {
              this.d.cssClass.split(' ').forEach(cssClass => {
                  renderer.setElementClass(_elementRef.nativeElement, cssClass, true);
              });
          }
          this.id = (++pickerIds);
          this.lastClick = 0;
      }
      ionViewWillLoad() {
          let data = this.d;
          data.buttons = data.buttons.map(button => {
              if (isString(button)) {
                  return { text: button };
              }
              if (button.role) {
                  button.cssRole = `picker-toolbar-${button.role}`;
              }
              return button;
          });
          data.columns = data.columns.map(column => {
              if (!isPresent(column.options)) {
                  column.options = [];
              }
              column.options = column.options.map(inputOpt => {
                  let opt = {
                      text: '',
                      value: '',
                      disabled: inputOpt.disabled,
                  };
                  if (isPresent(inputOpt)) {
                      if (isString(inputOpt) || isNumber(inputOpt)) {
                          opt.text = inputOpt.toString();
                          opt.value = inputOpt;
                      }
                      else {
                          opt.text = isPresent(inputOpt.text) ? inputOpt.text : inputOpt.value;
                          opt.value = isPresent(inputOpt.value) ? inputOpt.value : inputOpt.text;
                      }
                  }
                  return opt;
              });
              return column;
          });
      }
      ionViewWillEnter() {
          this._gestureBlocker.block();
      }
      ionViewDidLeave() {
          this._gestureBlocker.unblock();
      }
      refresh() {
          this._cols.forEach(column => {
              column.refresh();
          });
      }
      _colChange(selectedOption) {
          var picker = this._viewCtrl;
          picker.ionChange.emit(this.getSelected());
      }
      _keyUp(ev) {
          if (this.enabled && this._viewCtrl.isLast()) {
              if (ev.keyCode === Key.ENTER) {
                  if (this.lastClick + 1000 < Date.now()) {
                      (void 0);
                      let button = this.d.buttons[this.d.buttons.length - 1];
                      this.btnClick(button);
                  }
              }
              else if (ev.keyCode === Key.ESCAPE) {
                  (void 0);
                  this.bdClick();
              }
          }
      }
      ionViewDidEnter() {
          let activeElement = document.activeElement;
          if (activeElement) {
              activeElement.blur();
          }
          let focusableEle = this._elementRef.nativeElement.querySelector('button');
          if (focusableEle) {
              focusableEle.focus();
          }
          this.enabled = true;
      }
      btnClick(button, dismissDelay) {
          if (!this.enabled) {
              return;
          }
          this.lastClick = Date.now();
          let shouldDismiss = true;
          if (button.handler) {
              if (button.handler(this.getSelected()) === false) {
                  shouldDismiss = false;
              }
          }
          if (shouldDismiss) {
              setTimeout(() => {
                  this.dismiss(button.role);
              }, dismissDelay || this._config.get('pageTransitionDelay'));
          }
      }
      bdClick() {
          if (this.enabled && this.d.enableBackdropDismiss) {
              this.dismiss('backdrop');
          }
      }
      dismiss(role) {
          return this._viewCtrl.dismiss(this.getSelected(), role);
      }
      getSelected() {
          let selected = {};
          this.d.columns.forEach((col, index) => {
              let selectedColumn = col.options[col.selectedIndex];
              selected[col.name] = {
                  text: selectedColumn ? selectedColumn.text : null,
                  value: selectedColumn ? selectedColumn.value : null,
                  columnIndex: index,
              };
          });
          return selected;
      }
      ngOnDestroy() {
          (void 0);
          this._gestureBlocker.destroy();
      }
  }
  PickerCmp.decorators = [
      { type: Component, args: [{
                  selector: 'ion-picker-cmp',
                  template: `
      <ion-backdrop (click)="bdClick()"></ion-backdrop>
      <div class="picker-wrapper">
        <div class="picker-toolbar">
          <div *ngFor="let b of d.buttons" class="picker-toolbar-button" [ngClass]="b.cssRole">
            <button ion-button (click)="btnClick(b)" [ngClass]="b.cssClass" class="picker-button" clear>
              {{b.text}}
            </button>
          </div>
        </div>
        <div class="picker-columns">
          <div class="picker-above-highlight"></div>
          <div *ngFor="let c of d.columns" [col]="c" class="picker-col" (ionChange)="_colChange($event)"></div>
          <div class="picker-below-highlight"></div>
        </div>
      </div>
    `,
                  host: {
                      'role': 'dialog'
                  },
                  encapsulation: ViewEncapsulation.None,
              },] },
  ];
  PickerCmp.ctorParameters = [
      { type: ViewController, },
      { type: ElementRef, },
      { type: Config, },
      { type: GestureController, },
      { type: NavParams, },
      { type: Renderer, },
  ];
  PickerCmp.propDecorators = {
      '_cols': [{ type: ViewChildren, args: [PickerColumnCmp,] },],
      '_keyUp': [{ type: HostListener, args: ['body:keyup', ['$event'],] },],
  };
  let pickerIds = -1;
  const PICKER_OPT_SELECTED = 'picker-opt-selected';
  const DECELERATION_FRICTION = 0.97;
  const FRAME_MS = (1000 / 60);
  const MAX_PICKER_SPEED = 60;
  //# sourceMappingURL=picker-component.js.map