stepper.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /**
  2. * @license
  3. * Copyright Google LLC All Rights Reserved.
  4. *
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://angular.io/license
  7. */
  8. import { Directive, ElementRef, TemplateRef, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, EventEmitter, forwardRef, Inject, InjectionToken, Input, Optional, Output, ViewChild, ViewEncapsulation, HostListener, NgModule } from '@angular/core';
  9. import { FocusKeyManager } from '@angular/cdk/a11y';
  10. import { Directionality, BidiModule } from '@angular/cdk/bidi';
  11. import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
  12. import { END, ENTER, hasModifierKey, HOME, SPACE } from '@angular/cdk/keycodes';
  13. import { DOCUMENT, CommonModule } from '@angular/common';
  14. import { of, Subject } from 'rxjs';
  15. import { startWith, takeUntil } from 'rxjs/operators';
  16. /**
  17. * @fileoverview added by tsickle
  18. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  19. */
  20. class CdkStepHeader {
  21. /**
  22. * @param {?} _elementRef
  23. */
  24. constructor(_elementRef) {
  25. this._elementRef = _elementRef;
  26. }
  27. /**
  28. * Focuses the step header.
  29. * @return {?}
  30. */
  31. focus() {
  32. this._elementRef.nativeElement.focus();
  33. }
  34. }
  35. CdkStepHeader.decorators = [
  36. { type: Directive, args: [{
  37. selector: '[cdkStepHeader]',
  38. host: {
  39. 'role': 'tab',
  40. },
  41. },] },
  42. ];
  43. /** @nocollapse */
  44. CdkStepHeader.ctorParameters = () => [
  45. { type: ElementRef }
  46. ];
  47. /**
  48. * @fileoverview added by tsickle
  49. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  50. */
  51. class CdkStepLabel {
  52. /**
  53. * @param {?} template
  54. */
  55. constructor(/** @docs-private */ template) {
  56. this.template = template;
  57. }
  58. }
  59. CdkStepLabel.decorators = [
  60. { type: Directive, args: [{
  61. selector: '[cdkStepLabel]',
  62. },] },
  63. ];
  64. /** @nocollapse */
  65. CdkStepLabel.ctorParameters = () => [
  66. { type: TemplateRef }
  67. ];
  68. /**
  69. * @fileoverview added by tsickle
  70. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  71. */
  72. /**
  73. * Used to generate unique ID for each stepper component.
  74. * @type {?}
  75. */
  76. let nextId = 0;
  77. /**
  78. * Change event emitted on selection changes.
  79. */
  80. class StepperSelectionEvent {
  81. }
  82. /**
  83. * Enum to represent the different states of the steps.
  84. * @type {?}
  85. */
  86. const STEP_STATE = {
  87. NUMBER: 'number',
  88. EDIT: 'edit',
  89. DONE: 'done',
  90. ERROR: 'error'
  91. };
  92. /**
  93. * InjectionToken that can be used to specify the global stepper options.
  94. * @type {?}
  95. */
  96. const STEPPER_GLOBAL_OPTIONS = new InjectionToken('STEPPER_GLOBAL_OPTIONS');
  97. /**
  98. * InjectionToken that can be used to specify the global stepper options.
  99. * @deprecated Use `STEPPER_GLOBAL_OPTIONS` instead.
  100. * \@breaking-change 8.0.0.
  101. * @type {?}
  102. */
  103. const MAT_STEPPER_GLOBAL_OPTIONS = STEPPER_GLOBAL_OPTIONS;
  104. class CdkStep {
  105. /**
  106. * \@breaking-change 8.0.0 remove the `?` after `stepperOptions`
  107. * @param {?} _stepper
  108. * @param {?=} stepperOptions
  109. */
  110. constructor(_stepper, stepperOptions) {
  111. this._stepper = _stepper;
  112. /**
  113. * Whether user has seen the expanded step content or not.
  114. */
  115. this.interacted = false;
  116. this._editable = true;
  117. this._optional = false;
  118. this._completedOverride = null;
  119. this._customError = null;
  120. this._stepperOptions = stepperOptions ? stepperOptions : {};
  121. this._displayDefaultIndicatorType = this._stepperOptions.displayDefaultIndicatorType !== false;
  122. this._showError = !!this._stepperOptions.showError;
  123. }
  124. /**
  125. * Whether the user can return to this step once it has been marked as completed.
  126. * @return {?}
  127. */
  128. get editable() {
  129. return this._editable;
  130. }
  131. /**
  132. * @param {?} value
  133. * @return {?}
  134. */
  135. set editable(value) {
  136. this._editable = coerceBooleanProperty(value);
  137. }
  138. /**
  139. * Whether the completion of step is optional.
  140. * @return {?}
  141. */
  142. get optional() {
  143. return this._optional;
  144. }
  145. /**
  146. * @param {?} value
  147. * @return {?}
  148. */
  149. set optional(value) {
  150. this._optional = coerceBooleanProperty(value);
  151. }
  152. /**
  153. * Whether step is marked as completed.
  154. * @return {?}
  155. */
  156. get completed() {
  157. return this._completedOverride == null ? this._getDefaultCompleted() : this._completedOverride;
  158. }
  159. /**
  160. * @param {?} value
  161. * @return {?}
  162. */
  163. set completed(value) {
  164. this._completedOverride = coerceBooleanProperty(value);
  165. }
  166. /**
  167. * @private
  168. * @return {?}
  169. */
  170. _getDefaultCompleted() {
  171. return this.stepControl ? this.stepControl.valid && this.interacted : this.interacted;
  172. }
  173. /**
  174. * Whether step has an error.
  175. * @return {?}
  176. */
  177. get hasError() {
  178. return this._customError == null ? this._getDefaultError() : this._customError;
  179. }
  180. /**
  181. * @param {?} value
  182. * @return {?}
  183. */
  184. set hasError(value) {
  185. this._customError = coerceBooleanProperty(value);
  186. }
  187. /**
  188. * @private
  189. * @return {?}
  190. */
  191. _getDefaultError() {
  192. return this.stepControl && this.stepControl.invalid && this.interacted;
  193. }
  194. /**
  195. * Selects this step component.
  196. * @return {?}
  197. */
  198. select() {
  199. this._stepper.selected = this;
  200. }
  201. /**
  202. * Resets the step to its initial state. Note that this includes resetting form data.
  203. * @return {?}
  204. */
  205. reset() {
  206. this.interacted = false;
  207. if (this._completedOverride != null) {
  208. this._completedOverride = false;
  209. }
  210. if (this._customError != null) {
  211. this._customError = false;
  212. }
  213. if (this.stepControl) {
  214. this.stepControl.reset();
  215. }
  216. }
  217. /**
  218. * @return {?}
  219. */
  220. ngOnChanges() {
  221. // Since basically all inputs of the MatStep get proxied through the view down to the
  222. // underlying MatStepHeader, we have to make sure that change detection runs correctly.
  223. this._stepper._stateChanged();
  224. }
  225. }
  226. CdkStep.decorators = [
  227. { type: Component, args: [{selector: 'cdk-step',
  228. exportAs: 'cdkStep',
  229. template: '<ng-template><ng-content></ng-content></ng-template>',
  230. encapsulation: ViewEncapsulation.None,
  231. changeDetection: ChangeDetectionStrategy.OnPush,
  232. },] },
  233. ];
  234. /** @nocollapse */
  235. CdkStep.ctorParameters = () => [
  236. { type: CdkStepper, decorators: [{ type: Inject, args: [forwardRef((/**
  237. * @return {?}
  238. */
  239. () => CdkStepper)),] }] },
  240. { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [STEPPER_GLOBAL_OPTIONS,] }] }
  241. ];
  242. CdkStep.propDecorators = {
  243. stepLabel: [{ type: ContentChild, args: [CdkStepLabel, { static: false },] }],
  244. content: [{ type: ViewChild, args: [TemplateRef, { static: true },] }],
  245. stepControl: [{ type: Input }],
  246. label: [{ type: Input }],
  247. errorMessage: [{ type: Input }],
  248. ariaLabel: [{ type: Input, args: ['aria-label',] }],
  249. ariaLabelledby: [{ type: Input, args: ['aria-labelledby',] }],
  250. state: [{ type: Input }],
  251. editable: [{ type: Input }],
  252. optional: [{ type: Input }],
  253. completed: [{ type: Input }],
  254. hasError: [{ type: Input }]
  255. };
  256. class CdkStepper {
  257. /**
  258. * @param {?} _dir
  259. * @param {?} _changeDetectorRef
  260. * @param {?=} _elementRef
  261. * @param {?=} _document
  262. */
  263. constructor(_dir, _changeDetectorRef, _elementRef, _document) {
  264. this._dir = _dir;
  265. this._changeDetectorRef = _changeDetectorRef;
  266. this._elementRef = _elementRef;
  267. /**
  268. * Emits when the component is destroyed.
  269. */
  270. this._destroyed = new Subject();
  271. this._linear = false;
  272. this._selectedIndex = 0;
  273. /**
  274. * Event emitted when the selected step has changed.
  275. */
  276. this.selectionChange = new EventEmitter();
  277. this._orientation = 'horizontal';
  278. this._groupId = nextId++;
  279. this._document = _document;
  280. }
  281. /**
  282. * The list of step components that the stepper is holding.
  283. * @return {?}
  284. */
  285. get steps() {
  286. return this._steps;
  287. }
  288. /**
  289. * Whether the validity of previous steps should be checked or not.
  290. * @return {?}
  291. */
  292. get linear() {
  293. return this._linear;
  294. }
  295. /**
  296. * @param {?} value
  297. * @return {?}
  298. */
  299. set linear(value) {
  300. this._linear = coerceBooleanProperty(value);
  301. }
  302. /**
  303. * The index of the selected step.
  304. * @return {?}
  305. */
  306. get selectedIndex() {
  307. return this._selectedIndex;
  308. }
  309. /**
  310. * @param {?} index
  311. * @return {?}
  312. */
  313. set selectedIndex(index) {
  314. /** @type {?} */
  315. const newIndex = coerceNumberProperty(index);
  316. if (this.steps) {
  317. // Ensure that the index can't be out of bounds.
  318. if (newIndex < 0 || newIndex > this.steps.length - 1) {
  319. throw Error('cdkStepper: Cannot assign out-of-bounds value to `selectedIndex`.');
  320. }
  321. if (this._selectedIndex != newIndex && !this._anyControlsInvalidOrPending(newIndex) &&
  322. (newIndex >= this._selectedIndex || this.steps.toArray()[newIndex].editable)) {
  323. this._updateSelectedItemIndex(index);
  324. }
  325. }
  326. else {
  327. this._selectedIndex = newIndex;
  328. }
  329. }
  330. /**
  331. * The step that is selected.
  332. * @return {?}
  333. */
  334. get selected() {
  335. // @breaking-change 8.0.0 Change return type to `CdkStep | undefined`.
  336. return this.steps ? this.steps.toArray()[this.selectedIndex] : (/** @type {?} */ (undefined));
  337. }
  338. /**
  339. * @param {?} step
  340. * @return {?}
  341. */
  342. set selected(step) {
  343. this.selectedIndex = this.steps ? this.steps.toArray().indexOf(step) : -1;
  344. }
  345. /**
  346. * @return {?}
  347. */
  348. ngAfterViewInit() {
  349. // Note that while the step headers are content children by default, any components that
  350. // extend this one might have them as view chidren. We initialize the keyboard handling in
  351. // AfterViewInit so we're guaranteed for both view and content children to be defined.
  352. this._keyManager = new FocusKeyManager(this._stepHeader)
  353. .withWrap()
  354. .withVerticalOrientation(this._orientation === 'vertical');
  355. (this._dir ? ((/** @type {?} */ (this._dir.change))) : of())
  356. .pipe(startWith(this._layoutDirection()), takeUntil(this._destroyed))
  357. .subscribe((/**
  358. * @param {?} direction
  359. * @return {?}
  360. */
  361. direction => this._keyManager.withHorizontalOrientation(direction)));
  362. this._keyManager.updateActiveItemIndex(this._selectedIndex);
  363. this.steps.changes.pipe(takeUntil(this._destroyed)).subscribe((/**
  364. * @return {?}
  365. */
  366. () => {
  367. if (!this.selected) {
  368. this._selectedIndex = Math.max(this._selectedIndex - 1, 0);
  369. }
  370. }));
  371. }
  372. /**
  373. * @return {?}
  374. */
  375. ngOnDestroy() {
  376. this._destroyed.next();
  377. this._destroyed.complete();
  378. }
  379. /**
  380. * Selects and focuses the next step in list.
  381. * @return {?}
  382. */
  383. next() {
  384. this.selectedIndex = Math.min(this._selectedIndex + 1, this.steps.length - 1);
  385. }
  386. /**
  387. * Selects and focuses the previous step in list.
  388. * @return {?}
  389. */
  390. previous() {
  391. this.selectedIndex = Math.max(this._selectedIndex - 1, 0);
  392. }
  393. /**
  394. * Resets the stepper to its initial state. Note that this includes clearing form data.
  395. * @return {?}
  396. */
  397. reset() {
  398. this._updateSelectedItemIndex(0);
  399. this.steps.forEach((/**
  400. * @param {?} step
  401. * @return {?}
  402. */
  403. step => step.reset()));
  404. this._stateChanged();
  405. }
  406. /**
  407. * Returns a unique id for each step label element.
  408. * @param {?} i
  409. * @return {?}
  410. */
  411. _getStepLabelId(i) {
  412. return `cdk-step-label-${this._groupId}-${i}`;
  413. }
  414. /**
  415. * Returns unique id for each step content element.
  416. * @param {?} i
  417. * @return {?}
  418. */
  419. _getStepContentId(i) {
  420. return `cdk-step-content-${this._groupId}-${i}`;
  421. }
  422. /**
  423. * Marks the component to be change detected.
  424. * @return {?}
  425. */
  426. _stateChanged() {
  427. this._changeDetectorRef.markForCheck();
  428. }
  429. /**
  430. * Returns position state of the step with the given index.
  431. * @param {?} index
  432. * @return {?}
  433. */
  434. _getAnimationDirection(index) {
  435. /** @type {?} */
  436. const position = index - this._selectedIndex;
  437. if (position < 0) {
  438. return this._layoutDirection() === 'rtl' ? 'next' : 'previous';
  439. }
  440. else if (position > 0) {
  441. return this._layoutDirection() === 'rtl' ? 'previous' : 'next';
  442. }
  443. return 'current';
  444. }
  445. /**
  446. * Returns the type of icon to be displayed.
  447. * @param {?} index
  448. * @param {?=} state
  449. * @return {?}
  450. */
  451. _getIndicatorType(index, state = STEP_STATE.NUMBER) {
  452. /** @type {?} */
  453. const step = this.steps.toArray()[index];
  454. /** @type {?} */
  455. const isCurrentStep = this._isCurrentStep(index);
  456. return step._displayDefaultIndicatorType ? this._getDefaultIndicatorLogic(step, isCurrentStep) :
  457. this._getGuidelineLogic(step, isCurrentStep, state);
  458. }
  459. /**
  460. * @private
  461. * @param {?} step
  462. * @param {?} isCurrentStep
  463. * @return {?}
  464. */
  465. _getDefaultIndicatorLogic(step, isCurrentStep) {
  466. if (step._showError && step.hasError && !isCurrentStep) {
  467. return STEP_STATE.ERROR;
  468. }
  469. else if (!step.completed || isCurrentStep) {
  470. return STEP_STATE.NUMBER;
  471. }
  472. else {
  473. return step.editable ? STEP_STATE.EDIT : STEP_STATE.DONE;
  474. }
  475. }
  476. /**
  477. * @private
  478. * @param {?} step
  479. * @param {?} isCurrentStep
  480. * @param {?=} state
  481. * @return {?}
  482. */
  483. _getGuidelineLogic(step, isCurrentStep, state = STEP_STATE.NUMBER) {
  484. if (step._showError && step.hasError && !isCurrentStep) {
  485. return STEP_STATE.ERROR;
  486. }
  487. else if (step.completed && !isCurrentStep) {
  488. return STEP_STATE.DONE;
  489. }
  490. else if (step.completed && isCurrentStep) {
  491. return state;
  492. }
  493. else if (step.editable && isCurrentStep) {
  494. return STEP_STATE.EDIT;
  495. }
  496. else {
  497. return state;
  498. }
  499. }
  500. /**
  501. * @private
  502. * @param {?} index
  503. * @return {?}
  504. */
  505. _isCurrentStep(index) {
  506. return this._selectedIndex === index;
  507. }
  508. /**
  509. * Returns the index of the currently-focused step header.
  510. * @return {?}
  511. */
  512. _getFocusIndex() {
  513. return this._keyManager ? this._keyManager.activeItemIndex : this._selectedIndex;
  514. }
  515. /**
  516. * @private
  517. * @param {?} newIndex
  518. * @return {?}
  519. */
  520. _updateSelectedItemIndex(newIndex) {
  521. /** @type {?} */
  522. const stepsArray = this.steps.toArray();
  523. this.selectionChange.emit({
  524. selectedIndex: newIndex,
  525. previouslySelectedIndex: this._selectedIndex,
  526. selectedStep: stepsArray[newIndex],
  527. previouslySelectedStep: stepsArray[this._selectedIndex],
  528. });
  529. // If focus is inside the stepper, move it to the next header, otherwise it may become
  530. // lost when the active step content is hidden. We can't be more granular with the check
  531. // (e.g. checking whether focus is inside the active step), because we don't have a
  532. // reference to the elements that are rendering out the content.
  533. this._containsFocus() ? this._keyManager.setActiveItem(newIndex) :
  534. this._keyManager.updateActiveItemIndex(newIndex);
  535. this._selectedIndex = newIndex;
  536. this._stateChanged();
  537. }
  538. /**
  539. * @param {?} event
  540. * @return {?}
  541. */
  542. _onKeydown(event) {
  543. /** @type {?} */
  544. const hasModifier = hasModifierKey(event);
  545. /** @type {?} */
  546. const keyCode = event.keyCode;
  547. /** @type {?} */
  548. const manager = this._keyManager;
  549. if (manager.activeItemIndex != null && !hasModifier &&
  550. (keyCode === SPACE || keyCode === ENTER)) {
  551. this.selectedIndex = manager.activeItemIndex;
  552. event.preventDefault();
  553. }
  554. else if (keyCode === HOME) {
  555. manager.setFirstItemActive();
  556. event.preventDefault();
  557. }
  558. else if (keyCode === END) {
  559. manager.setLastItemActive();
  560. event.preventDefault();
  561. }
  562. else {
  563. manager.onKeydown(event);
  564. }
  565. }
  566. /**
  567. * @private
  568. * @param {?} index
  569. * @return {?}
  570. */
  571. _anyControlsInvalidOrPending(index) {
  572. /** @type {?} */
  573. const steps = this.steps.toArray();
  574. steps[this._selectedIndex].interacted = true;
  575. if (this._linear && index >= 0) {
  576. return steps.slice(0, index).some((/**
  577. * @param {?} step
  578. * @return {?}
  579. */
  580. step => {
  581. /** @type {?} */
  582. const control = step.stepControl;
  583. /** @type {?} */
  584. const isIncomplete = control ? (control.invalid || control.pending || !step.interacted) : !step.completed;
  585. return isIncomplete && !step.optional && !step._completedOverride;
  586. }));
  587. }
  588. return false;
  589. }
  590. /**
  591. * @private
  592. * @return {?}
  593. */
  594. _layoutDirection() {
  595. return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';
  596. }
  597. /**
  598. * Checks whether the stepper contains the focused element.
  599. * @private
  600. * @return {?}
  601. */
  602. _containsFocus() {
  603. if (!this._document || !this._elementRef) {
  604. return false;
  605. }
  606. /** @type {?} */
  607. const stepperElement = this._elementRef.nativeElement;
  608. /** @type {?} */
  609. const focusedElement = this._document.activeElement;
  610. return stepperElement === focusedElement || stepperElement.contains(focusedElement);
  611. }
  612. }
  613. CdkStepper.decorators = [
  614. { type: Directive, args: [{
  615. selector: '[cdkStepper]',
  616. exportAs: 'cdkStepper',
  617. },] },
  618. ];
  619. /** @nocollapse */
  620. CdkStepper.ctorParameters = () => [
  621. { type: Directionality, decorators: [{ type: Optional }] },
  622. { type: ChangeDetectorRef },
  623. { type: ElementRef },
  624. { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
  625. ];
  626. CdkStepper.propDecorators = {
  627. _steps: [{ type: ContentChildren, args: [CdkStep,] }],
  628. _stepHeader: [{ type: ContentChildren, args: [CdkStepHeader,] }],
  629. linear: [{ type: Input }],
  630. selectedIndex: [{ type: Input }],
  631. selected: [{ type: Input }],
  632. selectionChange: [{ type: Output }]
  633. };
  634. /**
  635. * @fileoverview added by tsickle
  636. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  637. */
  638. /**
  639. * Button that moves to the next step in a stepper workflow.
  640. */
  641. class CdkStepperNext {
  642. /**
  643. * @param {?} _stepper
  644. */
  645. constructor(_stepper) {
  646. this._stepper = _stepper;
  647. /**
  648. * Type of the next button. Defaults to "submit" if not specified.
  649. */
  650. this.type = 'submit';
  651. }
  652. // We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
  653. // In Ivy the `host` bindings will be merged when this class is extended, whereas in
  654. // ViewEngine they're overwritten.
  655. // TODO(crisbeto): we move this back into `host` once Ivy is turned on by default.
  656. // tslint:disable-next-line:no-host-decorator-in-concrete
  657. /**
  658. * @return {?}
  659. */
  660. _handleClick() {
  661. this._stepper.next();
  662. }
  663. }
  664. CdkStepperNext.decorators = [
  665. { type: Directive, args: [{
  666. selector: 'button[cdkStepperNext]',
  667. host: {
  668. '[type]': 'type',
  669. }
  670. },] },
  671. ];
  672. /** @nocollapse */
  673. CdkStepperNext.ctorParameters = () => [
  674. { type: CdkStepper }
  675. ];
  676. CdkStepperNext.propDecorators = {
  677. type: [{ type: Input }],
  678. _handleClick: [{ type: HostListener, args: ['click',] }]
  679. };
  680. /**
  681. * Button that moves to the previous step in a stepper workflow.
  682. */
  683. class CdkStepperPrevious {
  684. /**
  685. * @param {?} _stepper
  686. */
  687. constructor(_stepper) {
  688. this._stepper = _stepper;
  689. /**
  690. * Type of the previous button. Defaults to "button" if not specified.
  691. */
  692. this.type = 'button';
  693. }
  694. // We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
  695. // In Ivy the `host` bindings will be merged when this class is extended, whereas in
  696. // ViewEngine they're overwritten.
  697. // TODO(crisbeto): we move this back into `host` once Ivy is turned on by default.
  698. // tslint:disable-next-line:no-host-decorator-in-concrete
  699. /**
  700. * @return {?}
  701. */
  702. _handleClick() {
  703. this._stepper.previous();
  704. }
  705. }
  706. CdkStepperPrevious.decorators = [
  707. { type: Directive, args: [{
  708. selector: 'button[cdkStepperPrevious]',
  709. host: {
  710. '[type]': 'type',
  711. }
  712. },] },
  713. ];
  714. /** @nocollapse */
  715. CdkStepperPrevious.ctorParameters = () => [
  716. { type: CdkStepper }
  717. ];
  718. CdkStepperPrevious.propDecorators = {
  719. type: [{ type: Input }],
  720. _handleClick: [{ type: HostListener, args: ['click',] }]
  721. };
  722. /**
  723. * @fileoverview added by tsickle
  724. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  725. */
  726. class CdkStepperModule {
  727. }
  728. CdkStepperModule.decorators = [
  729. { type: NgModule, args: [{
  730. imports: [BidiModule, CommonModule],
  731. exports: [
  732. CdkStep,
  733. CdkStepper,
  734. CdkStepHeader,
  735. CdkStepLabel,
  736. CdkStepperNext,
  737. CdkStepperPrevious,
  738. ],
  739. declarations: [
  740. CdkStep,
  741. CdkStepper,
  742. CdkStepHeader,
  743. CdkStepLabel,
  744. CdkStepperNext,
  745. CdkStepperPrevious,
  746. ]
  747. },] },
  748. ];
  749. /**
  750. * @fileoverview added by tsickle
  751. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  752. */
  753. /**
  754. * @fileoverview added by tsickle
  755. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  756. */
  757. export { StepperSelectionEvent, STEP_STATE, STEPPER_GLOBAL_OPTIONS, MAT_STEPPER_GLOBAL_OPTIONS, CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious, CdkStepperModule, CdkStepHeader };
  758. //# sourceMappingURL=stepper.js.map