Skip to content

Commit

Permalink
Refactor code for shared functionality between vertical and horizonta…
Browse files Browse the repository at this point in the history
…l stepper
  • Loading branch information
jwshinjwshin committed Aug 18, 2017
1 parent edd0a03 commit 8ddc6db
Show file tree
Hide file tree
Showing 15 changed files with 239 additions and 86 deletions.
10 changes: 8 additions & 2 deletions src/cdk/stepper/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ import {CdkStepper, CdkStep} from './stepper';
import {CommonModule} from '@angular/common';
import {CdkStepLabel} from './step-label';
import {CdkStepperNext, CdkStepperPrevious} from './stepper-button';
import {CdkStepIcon} from './step-icon';
import {CdkStepLabelContainer} from './step-label-container';

@NgModule({
imports: [CommonModule],
exports: [CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious],
declarations: [CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious]
exports: [CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious, CdkStepIcon,
CdkStepLabelContainer],
declarations: [CdkStep, CdkStepper, CdkStepLabel, CdkStepperNext, CdkStepperPrevious, CdkStepIcon,
CdkStepLabelContainer]
})
export class CdkStepperModule {}

export * from './stepper';
export * from './step-label';
export * from './stepper-button';
export * from './step-icon';
export * from './step-label-container';
41 changes: 41 additions & 0 deletions src/cdk/stepper/step-icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, Input} from '@angular/core';
import {CdkStep} from './stepper';

@Directive({
selector: 'cdkStepIcon'
})
export class CdkStepIcon {
/** Step of the icon to be displayed. */
@Input()
step: CdkStep;

/** Whether the step of the icon to be displayed is active. */
@Input()
selected: boolean;

/** Index of the step. */
@Input()
index: number;

/** Whether the user has touched the step that is not selected. */
get notTouched() {
return this._getIndicatorType() == 'number' && !this.selected;
}

/** Returns the type of icon to be displayed. */
_getIndicatorType(): 'number' | 'edit' | 'done' {
if (!this.step.completed || this.selected) {
return 'number';
} else {
return this.step.editable ? 'edit' : 'done';
}
}
}
28 changes: 28 additions & 0 deletions src/cdk/stepper/step-label-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, Input} from '@angular/core';
import {CdkStep} from './stepper';

@Directive({
selector: 'cdkStepLabelContainer'
})
export class CdkStepLabelContainer {
/** Step of the label to be displayed. */
@Input()
step: CdkStep;

/** Whether the step of label to be displayed is selected. */
@Input()
selected: boolean;

/** Whether the label to be displayed is active. */
get active() {
return this.step.completed || this.selected;
}
}
9 changes: 0 additions & 9 deletions src/cdk/stepper/stepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,6 @@ export class CdkStepper {
}
}

_getIndicatorType(index: number): 'number' | 'edit' | 'done' {
const step = this._steps.toArray()[index];
if (!step.completed || this._selectedIndex == index) {
return 'number';
} else {
return step.editable ? 'edit' : 'done';
}
}

private _emitStepperSelectionEvent(newIndex: number): void {
const stepsArray = this._steps.toArray();
this.selectionChange.emit({
Expand Down
11 changes: 9 additions & 2 deletions src/lib/stepper/_stepper-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
color: mat-color($foreground, disabled-text);
}

.mat-step-indicator {
.mat-step-icon {
background-color: mat-color($primary);
color: mat-color($primary, default-contrast);
}
Expand All @@ -33,7 +33,14 @@
color: mat-color($foreground, disabled-text);
}

.mat-step-indicator-not-touched {
//.mat-step-icon {
// &.mat-step-indicator-not-touched {
//
// background-color: mat-color($foreground, disabled-text);
// }
//}

.mat-step-icon-not-touched {
background-color: mat-color($foreground, disabled-text);
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/lib/stepper/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {MdCommonModule} from '../core';
import {MdStepLabel} from './step-label';
import {MdStepperNext, MdStepperPrevious} from './stepper-button';
import {MdIconModule} from '../icon/index';
import {MdStepIcon} from './step-icon';
import {MdStepLabelContainer} from './step-label-container';

@NgModule({
imports: [
Expand All @@ -29,9 +31,9 @@ import {MdIconModule} from '../icon/index';
MdIconModule
],
exports: [MdCommonModule, MdHorizontalStepper, MdVerticalStepper, MdStep, MdStepLabel, MdStepper,
MdStepperNext, MdStepperPrevious],
MdStepperNext, MdStepperPrevious, MdStepIcon, MdStepLabelContainer],
declarations: [MdHorizontalStepper, MdVerticalStepper, MdStep, MdStepLabel, MdStepper,
MdStepperNext, MdStepperPrevious],
MdStepperNext, MdStepperPrevious, MdStepIcon, MdStepLabelContainer],
})
export class MdStepperModule {}

Expand All @@ -40,3 +42,5 @@ export * from './stepper-vertical';
export * from './step-label';
export * from './stepper';
export * from './stepper-button';
export * from './step-icon';
export * from './step-label-container';
5 changes: 5 additions & 0 deletions src/lib/stepper/step-icon.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div [ngSwitch]="_getIndicatorType()">
<span *ngSwitchCase="'number'">{{index + 1}}</span>
<md-icon *ngSwitchCase="'edit'">create</md-icon>
<md-icon *ngSwitchCase="'done'">done</md-icon>
</div>
83 changes: 83 additions & 0 deletions src/lib/stepper/step-icon.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {MdStepperModule} from './index';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component, ViewChild} from '@angular/core';
import {MdStep, MdStepper} from './stepper';
import {MdStepIcon} from './step-icon';
import {By} from '@angular/platform-browser';

describe('MdStepIcon', () => {

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdStepperModule],
declarations: [SimpleStepIconApp],
providers: [
{provide: MdStepper, useClass: MdStepper}
]
});
TestBed.compileComponents();
}));

describe('setting icon', () => {
let stepIconComponent: MdStepIcon;
let fixture: ComponentFixture<SimpleStepIconApp>;
let testComponent: SimpleStepIconApp;

beforeEach(() => {
fixture = TestBed.createComponent(SimpleStepIconApp);
fixture.detectChanges();

stepIconComponent = fixture.debugElement.query(By.css('md-step-icon')).componentInstance;
testComponent = fixture.componentInstance;
});

it('should set done icon if step is non-editable and completed', () => {
stepIconComponent.selected = true;
fixture.detectChanges();

expect(stepIconComponent._getIndicatorType()).toBe('number');

testComponent.mdStep.completed = true;
testComponent.mdStep.editable = false;
stepIconComponent.selected = false;
fixture.detectChanges();

expect(stepIconComponent._getIndicatorType()).toBe('done');
});

it('should set create icon if step is editable and completed', () => {
stepIconComponent.selected = true;
fixture.detectChanges();

expect(stepIconComponent._getIndicatorType()).toBe('number');

testComponent.mdStep.completed = true;
testComponent.mdStep.editable = true;
stepIconComponent.selected = false;
fixture.detectChanges();

expect(stepIconComponent._getIndicatorType()).toBe('edit');
});

it('should set "mat-step-icon-not-touched" class if the step ', () => {
let stepIconEl = fixture.debugElement.query(By.css('md-step-icon')).nativeElement;

testComponent.mdStep.completed = false;
stepIconComponent.selected = false;
fixture.detectChanges();

expect(stepIconComponent._getIndicatorType()).toBe('number');
expect(stepIconEl.classList).toContain('mat-step-icon-not-touched');
});
});
});

@Component({
template: `
<md-step>step</md-step>
<md-step-icon [step]="mdStep"></md-step-icon>
`
})
class SimpleStepIconApp {
@ViewChild(MdStep) mdStep: MdStep;
}
20 changes: 20 additions & 0 deletions src/lib/stepper/step-icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Component} from '@angular/core';
import {CdkStepIcon} from '@angular/cdk/stepper';

@Component({
selector: 'md-step-icon, mat-step-icon',
templateUrl: 'step-icon.html',
host: {
'class': 'mat-step-icon',
'[class.mat-step-icon-not-touched]': 'notTouched'
}
})
export class MdStepIcon extends CdkStepIcon { }
9 changes: 9 additions & 0 deletions src/lib/stepper/step-label-container.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div>
<!-- If there is a label template, use it. -->
<ng-container *ngIf="step.stepLabel" [ngTemplateOutlet]="step.stepLabel.template">
</ng-container>
<!-- It there is no label template, fall back to the text label. -->
<div *ngIf="!step.stepLabel">{{step.label}}</div>

<div class="mat-step-optional" *ngIf="step.optional">Optional</div>
</div>
20 changes: 20 additions & 0 deletions src/lib/stepper/step-label-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {Component} from '@angular/core';
import {CdkStepLabelContainer} from '@angular/cdk/stepper';

@Component({
selector: 'md-step-label-container, mat-step-label-container',
templateUrl: 'step-label-container.html',
host: {
'[class.mat-step-label-active]': 'active',
'[class.mat-step-label-inactive]': '!active'
}
})
export class MdStepLabelContainer extends CdkStepLabelContainer { }
24 changes: 4 additions & 20 deletions src/lib/stepper/stepper-horizontal.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,13 @@
[tabIndex]="_focusIndex == i ? 0 : -1"
(click)="step.select()"
(keydown)="_onKeydown($event)">
<div class="mat-step-indicator"
[ngSwitch]="_getIndicatorType(i)"
[class.mat-step-indicator-not-touched]="_getIndicatorType(i) == 'number'">
<span *ngSwitchCase="'number'">{{i + 1}}</span>
<md-icon *ngSwitchCase="'edit'">create</md-icon>
<md-icon *ngSwitchCase="'done'">done</md-icon>
</div>

<div [class.mat-stepper-label-active]="step.completed || selectedIndex == i"
[class.mat-stepper-label-inactive]="!step.completed && selectedIndex != i">
<!-- If there is a label template, use it. -->
<ng-container *ngIf="step.stepLabel" [ngTemplateOutlet]="step.stepLabel.template">
</ng-container>
<!-- It there is no label template, fall back to the text label. -->
<div *ngIf="!step.stepLabel">{{step.label}}</div>

<div class="mat-step-optional" *ngIf="step.optional">Optional</div>
</div>
</div>

<md-step-icon [step]="step" [selected]="selectedIndex == i" [index]="i"></md-step-icon>
<md-step-label-container [step]="step" [selected]="selectedIndex == i">
</md-step-label-container>
<div *ngIf="!isLast" class="mat-stepper-horizontal-line"></div>
</ng-container>
</div>

<div class="mat-horizontal-content-container">
<div *ngFor="let step of _steps; let i = index"
class="mat-horizontal-stepper-content" role="tabpanel"
Expand Down
21 changes: 3 additions & 18 deletions src/lib/stepper/stepper-vertical.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,9 @@
[tabIndex]="_focusIndex == i ? 0 : -1"
(click)="step.select()"
(keydown)="_onKeydown($event)">
<div class="mat-step-indicator"
[ngSwitch]="_getIndicatorType(i)"
[class.mat-step-indicator-not-touched]="_getIndicatorType(i) == 'number'">
<span *ngSwitchCase="'number'">{{i + 1}}</span>
<md-icon *ngSwitchCase="'edit'">create</md-icon>
<md-icon *ngSwitchCase="'done'">done</md-icon>
</div>

<div [class.mat-stepper-label-active]="step.completed || selectedIndex == i"
[class.mat-stepper-label-inactive]="!step.completed && selectedIndex != i">
<!-- If there is a label template, use it. -->
<ng-container *ngIf="step.stepLabel"[ngTemplateOutlet]="step.stepLabel.template">
</ng-container>
<!-- It there is no label template, fall back to the text label. -->
<div *ngIf="!step.stepLabel">{{step.label}}</div>

<div class="mat-step-optional" *ngIf="step.optional">Optional</div>
</div>
<md-step-icon [step]="step" [selected]="selectedIndex == i" [index]="i"></md-step-icon>
<md-step-label-container [step]="step" [selected]="selectedIndex == i">
</md-step-label-container>
</div>

<div class="mat-vertical-content-container" [class.mat-stepper-vertical-line]="!isLast">
Expand Down
6 changes: 3 additions & 3 deletions src/lib/stepper/stepper.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ $mat-step-optional-font-size: 12px;
vertical-align: middle;
}

.mat-step-indicator {
.mat-step-icon {
border-radius: 50%;
height: $mat-stepper-label-header-height;
width: $mat-stepper-label-header-height;
Expand All @@ -47,7 +47,7 @@ $mat-step-optional-font-size: 12px;
outline: none;
padding: 0 $mat-stepper-side-gap;

.mat-step-indicator {
.mat-step-icon {
margin-right: $mat-stepper-line-gap;
flex: none;
}
Expand All @@ -60,7 +60,7 @@ $mat-step-optional-font-size: 12px;
outline: none;
max-height: $mat-stepper-label-header-height;

.mat-step-indicator {
.mat-step-icon {
margin-right: $mat-vertical-stepper-content-margin - $mat-stepper-side-gap;
}
}
Expand Down
Loading

0 comments on commit 8ddc6db

Please sign in to comment.