Skip to content

Commit d5548d3

Browse files
committed
(wip) add adapter and fill in API
1 parent 2c0d003 commit d5548d3

File tree

1 file changed

+133
-9
lines changed

1 file changed

+133
-9
lines changed

src/material-experimental/mdc-progress-spinner/progress-spinner.ts

Lines changed: 133 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,156 @@
99
import {
1010
AfterViewInit,
1111
ChangeDetectionStrategy,
12-
Component,
13-
OnDestroy,
12+
Component, ElementRef, Inject, InjectionToken,
13+
Input, NgZone,
14+
OnDestroy, Optional,
1415
ViewEncapsulation
1516
} from '@angular/core';
16-
import {MDCCircularProgressFoundation} from '@material/circular-progress'
17+
import {
18+
MDCCircularProgressAdapter,
19+
MDCCircularProgressFoundation
20+
} from '@material/circular-progress';
21+
import {CanColor, CanColorCtor, mixinColor} from '@angular/material/core';
22+
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
23+
import {
24+
MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS,
25+
MatProgressSpinnerDefaultOptions
26+
} from '@angular/material/progress-spinner';
27+
import {coerceNumberProperty} from '@angular/cdk/coercion';
28+
29+
// Boilerplate for applying mixins to MatProgressBar.
30+
/** @docs-private */
31+
class MatProgressSpinnerBase {
32+
constructor(public _elementRef: ElementRef) { }
33+
}
34+
35+
const _MatProgressSpinnerMixinBase: CanColorCtor & typeof MatProgressSpinnerBase =
36+
mixinColor(MatProgressSpinnerBase, 'primary');
37+
38+
/**
39+
* Base reference size of the spinner.
40+
* @docs-private
41+
*/
42+
43+
export type ProgressSpinnerMode = 'determinate' | 'indeterminate';
44+
45+
const BASE_SIZE = 100;
1746

1847
@Component({
1948
selector: 'mat-progress-spinner',
2049
exportAs: 'matProgressSpinner',
50+
host: {
51+
'role': 'progressbar',
52+
'class': 'mat-progress-spinner',
53+
'[class._mat-animation-noopable]': `_noopAnimations`,
54+
'[style.width.px]': 'diameter',
55+
'[style.height.px]': 'diameter',
56+
'[attr.aria-valuemin]': 'mode === "determinate" ? 0 : null',
57+
'[attr.aria-valuemax]': 'mode === "determinate" ? 100 : null',
58+
'[attr.aria-valuenow]': 'mode === "determinate" ? value : null',
59+
'[attr.mode]': 'mode',
60+
},
61+
inputs: ['color'],
2162
templateUrl: 'progress-spinner.html',
2263
styleUrls: ['progress-spinner.css'],
2364
changeDetection: ChangeDetectionStrategy.OnPush,
2465
encapsulation: ViewEncapsulation.None,
2566
})
26-
export class MatProgressSpinner implements AfterViewInit, OnDestroy{
27-
private _circularProgressFoundation: MDCCircularProgressFoundation;
67+
export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements AfterViewInit, OnDestroy, CanColor {
68+
/** Implements all of the logic of the MDC circular progress. */
69+
private _foundation: MDCCircularProgressFoundation | undefined;
70+
71+
/** Adapter used by MDC to interact with the DOM. */
72+
private _adapter: MDCCircularProgressAdapter = {
73+
addClass: (className: string) => this._rootElement.classList.add(className),
74+
hasClass: (className: string) => this._rootElement.classList.contains(className),
75+
removeClass: (className: string) => this._rootElement.classList.remove(className),
76+
removeAttribute: (name: string) => this._rootElement.removeAttribute(name),
77+
setAttribute: (name: string, value: string) => this._rootElement.setAttribute(name, value),
78+
getDeterminateCircleAttribute: (attributeName: string) => this._determinateCircle.getAttribute(
79+
attributeName),
80+
setDeterminateCircleAttribute: (attributeName: string,
81+
value: string) => this._determinateCircle.setAttribute(
82+
attributeName,
83+
value),
84+
};
2885

29-
constructor() {
30-
this._circularProgressFoundation = new MDCCircularProgressFoundation();
86+
/** Whether the _mat-animation-noopable class should be applied, disabling animations. */
87+
_noopAnimations: boolean;
88+
89+
private _rootElement: HTMLElement;
90+
private _determinateCircle: HTMLElement;
91+
92+
constructor(public _elementRef: ElementRef<HTMLElement>, private _ngZone: NgZone,
93+
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode: string,
94+
@Inject(MAT_PROGRESS_SPINNER_DEFAULT_OPTIONS)
95+
defaults?: MatProgressSpinnerDefaultOptions) {
96+
super(_elementRef);
97+
this._noopAnimations = animationMode === 'NoopAnimations' &&
98+
(!!defaults && !defaults._forceAnimations);
3199
}
32100

101+
/**
102+
* Mode of the progress bar.
103+
*
104+
* Input must be one of these values: determinate, indeterminate, buffer, query, defaults to
105+
* 'determinate'.
106+
* Mirrored to mode attribute.
107+
*/
108+
@Input()
109+
get mode(): ProgressSpinnerMode {
110+
return this._mode;
111+
}
112+
113+
set mode(value: ProgressSpinnerMode) {
114+
// Note that we don't technically need a getter and a setter here,
115+
// but we use it to match the behavior of the existing mat-progress-bar.
116+
this._mode = value;
117+
this._syncFoundation();
118+
}
119+
private _mode: ProgressSpinnerMode = 'determinate';
120+
121+
122+
/** Value of the progress bar. Defaults to zero. Mirrored to aria-valuenow. */
123+
@Input()
124+
get value(): number {
125+
return this.mode === 'determinate' ? this._value : 0;
126+
}
127+
128+
set value(v: number) {
129+
this._value = Math.max(0, Math.min(100, coerceNumberProperty(v)));
130+
this._syncFoundation();
131+
}
132+
private _value = 0;
133+
134+
/** The diameter of the progress spinner (will set width and height of svg). */
135+
@Input()
136+
get diameter(): number { return this._diameter; }
137+
set diameter(size: number) {
138+
this._diameter = size;
139+
this._syncFoundation();
140+
}
141+
private _diameter = BASE_SIZE;
142+
33143
ngAfterViewInit() {
34-
this._circularProgressFoundation.init();
144+
this._foundation = new MDCCircularProgressFoundation(this._adapter);
145+
this._foundation.init();
146+
this._syncFoundation();
35147
}
36148

37149
ngOnDestroy() {
38-
this._circularProgressFoundation.destroy();
150+
if (this._foundation) {
151+
this._foundation.destroy();
152+
}
153+
}
154+
155+
private _syncFoundation() {
156+
const foundation = this._foundation;
157+
158+
if (foundation) {
159+
const mode = this.mode;
160+
foundation.setDeterminate(mode === 'determinate');
161+
foundation.setProgress(this.value / 100);
162+
}
39163
}
40164
}

0 commit comments

Comments
 (0)