source: trip-planner-front/node_modules/@angular/cdk/fesm2015/stepper.js@ 6c1585f

Last change on this file since 6c1585f was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 22.5 KB
Line 
1import { FocusKeyManager } from '@angular/cdk/a11y';
2import { Directionality, BidiModule } from '@angular/cdk/bidi';
3import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
4import { hasModifierKey, SPACE, ENTER } from '@angular/cdk/keycodes';
5import { DOCUMENT } from '@angular/common';
6import { Directive, ElementRef, TemplateRef, InjectionToken, EventEmitter, Component, ViewEncapsulation, ChangeDetectionStrategy, Inject, forwardRef, Optional, ContentChild, ViewChild, Input, Output, QueryList, ChangeDetectorRef, ContentChildren, HostListener, NgModule } from '@angular/core';
7import { _getFocusedElementPierceShadowDom } from '@angular/cdk/platform';
8import { Subject, of } from 'rxjs';
9import { startWith, takeUntil } from 'rxjs/operators';
10
11/**
12 * @license
13 * Copyright Google LLC All Rights Reserved.
14 *
15 * Use of this source code is governed by an MIT-style license that can be
16 * found in the LICENSE file at https://angular.io/license
17 */
18class CdkStepHeader {
19 constructor(_elementRef) {
20 this._elementRef = _elementRef;
21 }
22 /** Focuses the step header. */
23 focus() {
24 this._elementRef.nativeElement.focus();
25 }
26}
27CdkStepHeader.decorators = [
28 { type: Directive, args: [{
29 selector: '[cdkStepHeader]',
30 host: {
31 'role': 'tab',
32 },
33 },] }
34];
35CdkStepHeader.ctorParameters = () => [
36 { type: ElementRef }
37];
38
39/**
40 * @license
41 * Copyright Google LLC All Rights Reserved.
42 *
43 * Use of this source code is governed by an MIT-style license that can be
44 * found in the LICENSE file at https://angular.io/license
45 */
46class CdkStepLabel {
47 constructor(/** @docs-private */ template) {
48 this.template = template;
49 }
50}
51CdkStepLabel.decorators = [
52 { type: Directive, args: [{
53 selector: '[cdkStepLabel]',
54 },] }
55];
56CdkStepLabel.ctorParameters = () => [
57 { type: TemplateRef }
58];
59
60/**
61 * @license
62 * Copyright Google LLC All Rights Reserved.
63 *
64 * Use of this source code is governed by an MIT-style license that can be
65 * found in the LICENSE file at https://angular.io/license
66 */
67/** Used to generate unique ID for each stepper component. */
68let nextId = 0;
69/** Change event emitted on selection changes. */
70class StepperSelectionEvent {
71}
72/** Enum to represent the different states of the steps. */
73const STEP_STATE = {
74 NUMBER: 'number',
75 EDIT: 'edit',
76 DONE: 'done',
77 ERROR: 'error'
78};
79/** InjectionToken that can be used to specify the global stepper options. */
80const STEPPER_GLOBAL_OPTIONS = new InjectionToken('STEPPER_GLOBAL_OPTIONS');
81class CdkStep {
82 constructor(_stepper, stepperOptions) {
83 this._stepper = _stepper;
84 /** Whether user has attempted to move away from the step. */
85 this.interacted = false;
86 /** Emits when the user has attempted to move away from the step. */
87 this.interactedStream = new EventEmitter();
88 this._editable = true;
89 this._optional = false;
90 this._completedOverride = null;
91 this._customError = null;
92 this._stepperOptions = stepperOptions ? stepperOptions : {};
93 this._displayDefaultIndicatorType = this._stepperOptions.displayDefaultIndicatorType !== false;
94 }
95 /** Whether the user can return to this step once it has been marked as completed. */
96 get editable() {
97 return this._editable;
98 }
99 set editable(value) {
100 this._editable = coerceBooleanProperty(value);
101 }
102 /** Whether the completion of step is optional. */
103 get optional() {
104 return this._optional;
105 }
106 set optional(value) {
107 this._optional = coerceBooleanProperty(value);
108 }
109 /** Whether step is marked as completed. */
110 get completed() {
111 return this._completedOverride == null ? this._getDefaultCompleted() : this._completedOverride;
112 }
113 set completed(value) {
114 this._completedOverride = coerceBooleanProperty(value);
115 }
116 _getDefaultCompleted() {
117 return this.stepControl ? this.stepControl.valid && this.interacted : this.interacted;
118 }
119 /** Whether step has an error. */
120 get hasError() {
121 return this._customError == null ? this._getDefaultError() : this._customError;
122 }
123 set hasError(value) {
124 this._customError = coerceBooleanProperty(value);
125 }
126 _getDefaultError() {
127 return this.stepControl && this.stepControl.invalid && this.interacted;
128 }
129 /** Selects this step component. */
130 select() {
131 this._stepper.selected = this;
132 }
133 /** Resets the step to its initial state. Note that this includes resetting form data. */
134 reset() {
135 this.interacted = false;
136 if (this._completedOverride != null) {
137 this._completedOverride = false;
138 }
139 if (this._customError != null) {
140 this._customError = false;
141 }
142 if (this.stepControl) {
143 this.stepControl.reset();
144 }
145 }
146 ngOnChanges() {
147 // Since basically all inputs of the MatStep get proxied through the view down to the
148 // underlying MatStepHeader, we have to make sure that change detection runs correctly.
149 this._stepper._stateChanged();
150 }
151 _markAsInteracted() {
152 if (!this.interacted) {
153 this.interacted = true;
154 this.interactedStream.emit(this);
155 }
156 }
157 /** Determines whether the error state can be shown. */
158 _showError() {
159 var _a;
160 // We want to show the error state either if the user opted into/out of it using the
161 // global options, or if they've explicitly set it through the `hasError` input.
162 return (_a = this._stepperOptions.showError) !== null && _a !== void 0 ? _a : this._customError != null;
163 }
164}
165CdkStep.decorators = [
166 { type: Component, args: [{
167 selector: 'cdk-step',
168 exportAs: 'cdkStep',
169 template: '<ng-template><ng-content></ng-content></ng-template>',
170 encapsulation: ViewEncapsulation.None,
171 changeDetection: ChangeDetectionStrategy.OnPush
172 },] }
173];
174CdkStep.ctorParameters = () => [
175 { type: CdkStepper, decorators: [{ type: Inject, args: [forwardRef(() => CdkStepper),] }] },
176 { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [STEPPER_GLOBAL_OPTIONS,] }] }
177];
178CdkStep.propDecorators = {
179 stepLabel: [{ type: ContentChild, args: [CdkStepLabel,] }],
180 content: [{ type: ViewChild, args: [TemplateRef, { static: true },] }],
181 stepControl: [{ type: Input }],
182 interactedStream: [{ type: Output, args: ['interacted',] }],
183 label: [{ type: Input }],
184 errorMessage: [{ type: Input }],
185 ariaLabel: [{ type: Input, args: ['aria-label',] }],
186 ariaLabelledby: [{ type: Input, args: ['aria-labelledby',] }],
187 state: [{ type: Input }],
188 editable: [{ type: Input }],
189 optional: [{ type: Input }],
190 completed: [{ type: Input }],
191 hasError: [{ type: Input }]
192};
193class CdkStepper {
194 constructor(_dir, _changeDetectorRef, _elementRef,
195 /**
196 * @deprecated No longer in use, to be removed.
197 * @breaking-change 13.0.0
198 */
199 _document) {
200 this._dir = _dir;
201 this._changeDetectorRef = _changeDetectorRef;
202 this._elementRef = _elementRef;
203 /** Emits when the component is destroyed. */
204 this._destroyed = new Subject();
205 /** Steps that belong to the current stepper, excluding ones from nested steppers. */
206 this.steps = new QueryList();
207 /** List of step headers sorted based on their DOM order. */
208 this._sortedHeaders = new QueryList();
209 this._linear = false;
210 this._selectedIndex = 0;
211 /** Event emitted when the selected step has changed. */
212 this.selectionChange = new EventEmitter();
213 /**
214 * @deprecated To be turned into a private property. Use `orientation` instead.
215 * @breaking-change 13.0.0
216 */
217 this._orientation = 'horizontal';
218 this._groupId = nextId++;
219 }
220 /** Whether the validity of previous steps should be checked or not. */
221 get linear() {
222 return this._linear;
223 }
224 set linear(value) {
225 this._linear = coerceBooleanProperty(value);
226 }
227 /** The index of the selected step. */
228 get selectedIndex() {
229 return this._selectedIndex;
230 }
231 set selectedIndex(index) {
232 var _a;
233 const newIndex = coerceNumberProperty(index);
234 if (this.steps && this._steps) {
235 // Ensure that the index can't be out of bounds.
236 if (!this._isValidIndex(index) && (typeof ngDevMode === 'undefined' || ngDevMode)) {
237 throw Error('cdkStepper: Cannot assign out-of-bounds value to `selectedIndex`.');
238 }
239 (_a = this.selected) === null || _a === void 0 ? void 0 : _a._markAsInteracted();
240 if (this._selectedIndex !== newIndex && !this._anyControlsInvalidOrPending(newIndex) &&
241 (newIndex >= this._selectedIndex || this.steps.toArray()[newIndex].editable)) {
242 this._updateSelectedItemIndex(index);
243 }
244 }
245 else {
246 this._selectedIndex = newIndex;
247 }
248 }
249 /** The step that is selected. */
250 get selected() {
251 return this.steps ? this.steps.toArray()[this.selectedIndex] : undefined;
252 }
253 set selected(step) {
254 this.selectedIndex = (step && this.steps) ? this.steps.toArray().indexOf(step) : -1;
255 }
256 /** Orientation of the stepper. */
257 get orientation() { return this._orientation; }
258 set orientation(value) {
259 // This is a protected method so that `MatSteppter` can hook into it.
260 this._orientation = value;
261 if (this._keyManager) {
262 this._keyManager.withVerticalOrientation(value === 'vertical');
263 }
264 }
265 ngAfterContentInit() {
266 this._steps.changes
267 .pipe(startWith(this._steps), takeUntil(this._destroyed))
268 .subscribe((steps) => {
269 this.steps.reset(steps.filter(step => step._stepper === this));
270 this.steps.notifyOnChanges();
271 });
272 }
273 ngAfterViewInit() {
274 // If the step headers are defined outside of the `ngFor` that renders the steps, like in the
275 // Material stepper, they won't appear in the `QueryList` in the same order as they're
276 // rendered in the DOM which will lead to incorrect keyboard navigation. We need to sort
277 // them manually to ensure that they're correct. Alternatively, we can change the Material
278 // template to inline the headers in the `ngFor`, but that'll result in a lot of
279 // code duplciation. See #23539.
280 this._stepHeader.changes
281 .pipe(startWith(this._stepHeader), takeUntil(this._destroyed))
282 .subscribe((headers) => {
283 this._sortedHeaders.reset(headers.toArray().sort((a, b) => {
284 const documentPosition = a._elementRef.nativeElement.compareDocumentPosition(b._elementRef.nativeElement);
285 // `compareDocumentPosition` returns a bitmask so we have to use a bitwise operator.
286 // https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
287 // tslint:disable-next-line:no-bitwise
288 return documentPosition & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
289 }));
290 this._sortedHeaders.notifyOnChanges();
291 });
292 // Note that while the step headers are content children by default, any components that
293 // extend this one might have them as view children. We initialize the keyboard handling in
294 // AfterViewInit so we're guaranteed for both view and content children to be defined.
295 this._keyManager = new FocusKeyManager(this._sortedHeaders)
296 .withWrap()
297 .withHomeAndEnd()
298 .withVerticalOrientation(this._orientation === 'vertical');
299 (this._dir ? this._dir.change : of())
300 .pipe(startWith(this._layoutDirection()), takeUntil(this._destroyed))
301 .subscribe(direction => this._keyManager.withHorizontalOrientation(direction));
302 this._keyManager.updateActiveItem(this._selectedIndex);
303 // No need to `takeUntil` here, because we're the ones destroying `steps`.
304 this.steps.changes.subscribe(() => {
305 if (!this.selected) {
306 this._selectedIndex = Math.max(this._selectedIndex - 1, 0);
307 }
308 });
309 // The logic which asserts that the selected index is within bounds doesn't run before the
310 // steps are initialized, because we don't how many steps there are yet so we may have an
311 // invalid index on init. If that's the case, auto-correct to the default so we don't throw.
312 if (!this._isValidIndex(this._selectedIndex)) {
313 this._selectedIndex = 0;
314 }
315 }
316 ngOnDestroy() {
317 this.steps.destroy();
318 this._sortedHeaders.destroy();
319 this._destroyed.next();
320 this._destroyed.complete();
321 }
322 /** Selects and focuses the next step in list. */
323 next() {
324 this.selectedIndex = Math.min(this._selectedIndex + 1, this.steps.length - 1);
325 }
326 /** Selects and focuses the previous step in list. */
327 previous() {
328 this.selectedIndex = Math.max(this._selectedIndex - 1, 0);
329 }
330 /** Resets the stepper to its initial state. Note that this includes clearing form data. */
331 reset() {
332 this._updateSelectedItemIndex(0);
333 this.steps.forEach(step => step.reset());
334 this._stateChanged();
335 }
336 /** Returns a unique id for each step label element. */
337 _getStepLabelId(i) {
338 return `cdk-step-label-${this._groupId}-${i}`;
339 }
340 /** Returns unique id for each step content element. */
341 _getStepContentId(i) {
342 return `cdk-step-content-${this._groupId}-${i}`;
343 }
344 /** Marks the component to be change detected. */
345 _stateChanged() {
346 this._changeDetectorRef.markForCheck();
347 }
348 /** Returns position state of the step with the given index. */
349 _getAnimationDirection(index) {
350 const position = index - this._selectedIndex;
351 if (position < 0) {
352 return this._layoutDirection() === 'rtl' ? 'next' : 'previous';
353 }
354 else if (position > 0) {
355 return this._layoutDirection() === 'rtl' ? 'previous' : 'next';
356 }
357 return 'current';
358 }
359 /** Returns the type of icon to be displayed. */
360 _getIndicatorType(index, state = STEP_STATE.NUMBER) {
361 const step = this.steps.toArray()[index];
362 const isCurrentStep = this._isCurrentStep(index);
363 return step._displayDefaultIndicatorType ? this._getDefaultIndicatorLogic(step, isCurrentStep) :
364 this._getGuidelineLogic(step, isCurrentStep, state);
365 }
366 _getDefaultIndicatorLogic(step, isCurrentStep) {
367 if (step._showError() && step.hasError && !isCurrentStep) {
368 return STEP_STATE.ERROR;
369 }
370 else if (!step.completed || isCurrentStep) {
371 return STEP_STATE.NUMBER;
372 }
373 else {
374 return step.editable ? STEP_STATE.EDIT : STEP_STATE.DONE;
375 }
376 }
377 _getGuidelineLogic(step, isCurrentStep, state = STEP_STATE.NUMBER) {
378 if (step._showError() && step.hasError && !isCurrentStep) {
379 return STEP_STATE.ERROR;
380 }
381 else if (step.completed && !isCurrentStep) {
382 return STEP_STATE.DONE;
383 }
384 else if (step.completed && isCurrentStep) {
385 return state;
386 }
387 else if (step.editable && isCurrentStep) {
388 return STEP_STATE.EDIT;
389 }
390 else {
391 return state;
392 }
393 }
394 _isCurrentStep(index) {
395 return this._selectedIndex === index;
396 }
397 /** Returns the index of the currently-focused step header. */
398 _getFocusIndex() {
399 return this._keyManager ? this._keyManager.activeItemIndex : this._selectedIndex;
400 }
401 _updateSelectedItemIndex(newIndex) {
402 const stepsArray = this.steps.toArray();
403 this.selectionChange.emit({
404 selectedIndex: newIndex,
405 previouslySelectedIndex: this._selectedIndex,
406 selectedStep: stepsArray[newIndex],
407 previouslySelectedStep: stepsArray[this._selectedIndex],
408 });
409 // If focus is inside the stepper, move it to the next header, otherwise it may become
410 // lost when the active step content is hidden. We can't be more granular with the check
411 // (e.g. checking whether focus is inside the active step), because we don't have a
412 // reference to the elements that are rendering out the content.
413 this._containsFocus() ? this._keyManager.setActiveItem(newIndex) :
414 this._keyManager.updateActiveItem(newIndex);
415 this._selectedIndex = newIndex;
416 this._stateChanged();
417 }
418 _onKeydown(event) {
419 const hasModifier = hasModifierKey(event);
420 const keyCode = event.keyCode;
421 const manager = this._keyManager;
422 if (manager.activeItemIndex != null && !hasModifier &&
423 (keyCode === SPACE || keyCode === ENTER)) {
424 this.selectedIndex = manager.activeItemIndex;
425 event.preventDefault();
426 }
427 else {
428 manager.onKeydown(event);
429 }
430 }
431 _anyControlsInvalidOrPending(index) {
432 if (this._linear && index >= 0) {
433 return this.steps.toArray().slice(0, index).some(step => {
434 const control = step.stepControl;
435 const isIncomplete = control ? (control.invalid || control.pending || !step.interacted) : !step.completed;
436 return isIncomplete && !step.optional && !step._completedOverride;
437 });
438 }
439 return false;
440 }
441 _layoutDirection() {
442 return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';
443 }
444 /** Checks whether the stepper contains the focused element. */
445 _containsFocus() {
446 const stepperElement = this._elementRef.nativeElement;
447 const focusedElement = _getFocusedElementPierceShadowDom();
448 return stepperElement === focusedElement || stepperElement.contains(focusedElement);
449 }
450 /** Checks whether the passed-in index is a valid step index. */
451 _isValidIndex(index) {
452 return index > -1 && (!this.steps || index < this.steps.length);
453 }
454}
455CdkStepper.decorators = [
456 { type: Directive, args: [{
457 selector: '[cdkStepper]',
458 exportAs: 'cdkStepper',
459 },] }
460];
461CdkStepper.ctorParameters = () => [
462 { type: Directionality, decorators: [{ type: Optional }] },
463 { type: ChangeDetectorRef },
464 { type: ElementRef },
465 { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
466];
467CdkStepper.propDecorators = {
468 _steps: [{ type: ContentChildren, args: [CdkStep, { descendants: true },] }],
469 _stepHeader: [{ type: ContentChildren, args: [CdkStepHeader, { descendants: true },] }],
470 linear: [{ type: Input }],
471 selectedIndex: [{ type: Input }],
472 selected: [{ type: Input }],
473 selectionChange: [{ type: Output }],
474 orientation: [{ type: Input }]
475};
476
477/**
478 * @license
479 * Copyright Google LLC All Rights Reserved.
480 *
481 * Use of this source code is governed by an MIT-style license that can be
482 * found in the LICENSE file at https://angular.io/license
483 */
484/** Button that moves to the next step in a stepper workflow. */
485class CdkStepperNext {
486 constructor(_stepper) {
487 this._stepper = _stepper;
488 /** Type of the next button. Defaults to "submit" if not specified. */
489 this.type = 'submit';
490 }
491 // We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
492 // In Ivy the `host` bindings will be merged when this class is extended, whereas in
493 // ViewEngine they're overwritten.
494 // TODO(crisbeto): we move this back into `host` once Ivy is turned on by default.
495 // tslint:disable-next-line:no-host-decorator-in-concrete
496 _handleClick() {
497 this._stepper.next();
498 }
499}
500CdkStepperNext.decorators = [
501 { type: Directive, args: [{
502 selector: 'button[cdkStepperNext]',
503 host: {
504 '[type]': 'type',
505 }
506 },] }
507];
508CdkStepperNext.ctorParameters = () => [
509 { type: CdkStepper }
510];
511CdkStepperNext.propDecorators = {
512 type: [{ type: Input }],
513 _handleClick: [{ type: HostListener, args: ['click',] }]
514};
515/** Button that moves to the previous step in a stepper workflow. */
516class CdkStepperPrevious {
517 constructor(_stepper) {
518 this._stepper = _stepper;
519 /** Type of the previous button. Defaults to "button" if not specified. */
520 this.type = 'button';
521 }
522 // We have to use a `HostListener` here in order to support both Ivy and ViewEngine.
523 // In Ivy the `host` bindings will be merged when this class is extended, whereas in
524 // ViewEngine they're overwritten.
525 // TODO(crisbeto): we move this back into `host` once Ivy is turned on by default.
526 // tslint:disable-next-line:no-host-decorator-in-concrete
527 _handleClick() {
528 this._stepper.previous();
529 }
530}
531CdkStepperPrevious.decorators = [
532 { type: Directive, args: [{
533 selector: 'button[cdkStepperPrevious]',
534 host: {
535 '[type]': 'type',
536 }
537 },] }
538];
539CdkStepperPrevious.ctorParameters = () => [
540 { type: CdkStepper }
541];
542CdkStepperPrevious.propDecorators = {
543 type: [{ type: Input }],
544 _handleClick: [{ type: HostListener, args: ['click',] }]
545};
546
547/**
548 * @license
549 * Copyright Google LLC All Rights Reserved.
550 *
551 * Use of this source code is governed by an MIT-style license that can be
552 * found in the LICENSE file at https://angular.io/license
553 */
554class CdkStepperModule {
555}
556CdkStepperModule.decorators = [
557 { type: NgModule, args: [{
558 imports: [BidiModule],
559 exports: [
560 CdkStep,
561 CdkStepper,
562 CdkStepHeader,
563 CdkStepLabel,
564 CdkStepperNext,
565 CdkStepperPrevious,
566 ],
567 declarations: [
568 CdkStep,
569 CdkStepper,
570 CdkStepHeader,
571 CdkStepLabel,
572 CdkStepperNext,
573 CdkStepperPrevious,
574 ]
575 },] }
576];
577
578/**
579 * @license
580 * Copyright Google LLC All Rights Reserved.
581 *
582 * Use of this source code is governed by an MIT-style license that can be
583 * found in the LICENSE file at https://angular.io/license
584 */
585
586/**
587 * Generated bundle index. Do not edit.
588 */
589
590export { CdkStep, CdkStepHeader, CdkStepLabel, CdkStepper, CdkStepperModule, CdkStepperNext, CdkStepperPrevious, STEPPER_GLOBAL_OPTIONS, STEP_STATE, StepperSelectionEvent };
591//# sourceMappingURL=stepper.js.map
Note: See TracBrowser for help on using the repository browser.