diff --git a/README.md b/README.md
index d039d266e..dfc2ff44f 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ Using Google Material Components [foundations and adapters](https://github.com/m
| card | Available | [View](https://trimox.github.io/angular-mdc-web/#/card-demo) |
| checkbox | Available | [View](https://trimox.github.io/angular-mdc-web/#/checkbox-demo) |
| chips | Available | [View](https://trimox.github.io/angular-mdc-web/#/chips-demo) |
+| circular-progress | Available | [View](https://trimox.github.io/angular-mdc-web/#/circular-progress) |
| data-table | Available | [View](https://trimox.github.io/angular-mdc-web/#/data-table-demo) |
| dialog | Available | [View](https://trimox.github.io/angular-mdc-web/#/dialog-demo) |
| drawer | Available | [View](https://trimox.github.io/angular-mdc-web/#/drawer-demo) |
diff --git a/demos/src/app/app-routing.module.ts b/demos/src/app/app-routing.module.ts
index f17dbc454..e091a7276 100644
--- a/demos/src/app/app-routing.module.ts
+++ b/demos/src/app/app-routing.module.ts
@@ -19,6 +19,10 @@ const routes: Routes = [
path: 'checkbox-demo', loadChildren: () =>
import('./components/checkbox/module').then(m => m.CheckboxModule)
},
+ {
+ path: 'circular-progress', loadChildren: () =>
+ import('./components/circular-progress/module').then(m => m.CircularProgressModule)
+ },
{
path: 'chips-demo', loadChildren: () =>
import('./components/chips/module').then(m => m.ChipsModule)
diff --git a/demos/src/app/app.component.ts b/demos/src/app/app.component.ts
index 482188118..55dfb8e81 100644
--- a/demos/src/app/app.component.ts
+++ b/demos/src/app/app.component.ts
@@ -26,6 +26,7 @@ export class AppComponent implements OnInit {
{name: 'Card', route: 'card-demo'},
{name: 'Checkbox', route: 'checkbox-demo'},
{name: 'Chips', route: 'chips-demo'},
+ {name: 'Circular Progress', route: 'circular-progress'},
{name: 'Data Table', route: 'data-table-demo'},
{name: 'Dialog', route: 'dialog-demo'},
{name: 'Drawer', route: 'drawer-demo'},
diff --git a/demos/src/app/components/circular-progress/api.html b/demos/src/app/components/circular-progress/api.html
new file mode 100644
index 000000000..e69de29bb
diff --git a/demos/src/app/components/circular-progress/circular-progress.ts b/demos/src/app/components/circular-progress/circular-progress.ts
new file mode 100644
index 000000000..cd9b6e4de
--- /dev/null
+++ b/demos/src/app/components/circular-progress/circular-progress.ts
@@ -0,0 +1,44 @@
+import {Component, OnInit, ViewChild} from '@angular/core';
+
+import {ComponentViewer} from '../../shared/component-viewer';
+import {MdcSliderChange} from '@angular-mdc/web/slider';
+
+@Component({templateUrl: './api.html'})
+export class Api {}
+
+@Component({templateUrl: './sass.html'})
+export class Sass {}
+
+@Component({template: ' '})
+export class CircularProgress implements OnInit {
+ @ViewChild(ComponentViewer, {static: true}) _componentViewer: ComponentViewer;
+
+ ngOnInit(): void {
+ this._componentViewer.template = {
+ title: 'Circular Progress',
+ description: `Circular progress indicators display progress by animating an indicator
+ along an invisible circular track in a clockwise direction. They can be applied directly to a surface, such as a button or card.`,
+ references: [{
+ name: 'Material Design guidelines: Circular Progress',
+ url: 'https://material.io/components/progress-indicators/#circular-progress-indicators'
+ }, {
+ name: 'Material Components Web',
+ url: 'https://github.com/material-components/material-components-web/blob/master/packages/mdc-circular-progress/README.md'
+ }],
+ code: `import {MdcCircularProgressModule} from '@angular-mdc/web';`,
+ sass: `@use '@material/circular-progress/mdc-circular-progress';
+@use '@material/mdc-circular-progress';`
+ };
+ }
+}
+
+@Component({templateUrl: './examples.html'})
+export class Examples {
+ onInput(event: MdcSliderChange): void {
+ // this.continuousInputEventValue = event.value;
+ }
+
+ onChange(event: MdcSliderChange): void {
+ // this.continuousChangeEventValue = event.value;
+ }
+}
diff --git a/demos/src/app/components/circular-progress/examples.html b/demos/src/app/components/circular-progress/examples.html
new file mode 100644
index 000000000..44889de94
--- /dev/null
+++ b/demos/src/app/components/circular-progress/examples.html
@@ -0,0 +1,32 @@
+
+
+
+
Determinate
+
+
+
+
+
+ {{sliderForLarge.value}}
+
+
+
+
+
+
Medium
+
+
+
+
+
+
Small
+
+
+
\ No newline at end of file
diff --git a/demos/src/app/components/circular-progress/module.ts b/demos/src/app/components/circular-progress/module.ts
new file mode 100644
index 000000000..5866b574c
--- /dev/null
+++ b/demos/src/app/components/circular-progress/module.ts
@@ -0,0 +1,13 @@
+import {NgModule} from '@angular/core';
+
+import {SharedModule} from '../../shared.module';
+import {RoutingModule, ROUTE_DECLARATIONS} from './routing.module';
+
+@NgModule({
+ imports: [
+ SharedModule,
+ RoutingModule
+ ],
+ declarations: [ROUTE_DECLARATIONS]
+})
+export class CircularProgressModule {}
diff --git a/demos/src/app/components/circular-progress/routing.module.ts b/demos/src/app/components/circular-progress/routing.module.ts
new file mode 100644
index 000000000..b457535fa
--- /dev/null
+++ b/demos/src/app/components/circular-progress/routing.module.ts
@@ -0,0 +1,29 @@
+import {NgModule} from '@angular/core';
+import {Routes, RouterModule} from '@angular/router';
+
+import {Api, Examples, Sass, CircularProgress} from './circular-progress';
+
+export const ROUTE_DECLARATIONS = [
+ Api,
+ Examples,
+ Sass,
+ CircularProgress
+];
+
+const ROUTES: Routes = [
+ {
+ path: '', component: CircularProgress,
+ children: [
+ {path: '', redirectTo: 'api'},
+ {path: 'api', component: Api},
+ {path: 'sass', component: Sass},
+ {path: 'examples', component: Examples}
+ ]
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(ROUTES)],
+ exports: [RouterModule]
+})
+export class RoutingModule {}
diff --git a/demos/src/app/components/circular-progress/sass.html b/demos/src/app/components/circular-progress/sass.html
new file mode 100644
index 000000000..e69de29bb
diff --git a/demos/src/app/material.module.ts b/demos/src/app/material.module.ts
index 49bf1c349..8b24f65cc 100644
--- a/demos/src/app/material.module.ts
+++ b/demos/src/app/material.module.ts
@@ -1,6 +1,7 @@
import {NgModule} from '@angular/core';
import {MdcTopAppBarModule} from '@angular-mdc/web/top-app-bar';
+import {MdcCircularProgressModule} from '@angular-mdc/web/circular-progress';
import {MdcIconModule} from '@angular-mdc/web/icon';
import {MdcDrawerModule} from '@angular-mdc/web/drawer';
import {MdcListModule} from '@angular-mdc/web/list';
@@ -31,6 +32,7 @@ const MDC_MODULES = [
MdcCardModule,
MdcCheckboxModule,
MdcChipsModule,
+ MdcCircularProgressModule,
MDCDataTableModule,
MdcDialogModule,
MdcDrawerModule,
diff --git a/demos/src/styles/_mdc.scss b/demos/src/styles/_mdc.scss
index 532f9e730..1dc8b8588 100644
--- a/demos/src/styles/_mdc.scss
+++ b/demos/src/styles/_mdc.scss
@@ -4,6 +4,7 @@
@use '@material/button/mdc-button';
@use '@material/drawer/mdc-drawer';
@use '@material/list/mdc-list';
+@use '@material/circular-progress/mdc-circular-progress';
@use '@material/elevation/mdc-elevation';
@use '@material/icon-button/mdc-icon-button';
@use '@material/top-app-bar/mdc-top-app-bar';
diff --git a/packages/circular-progress/BUILD.bazel b/packages/circular-progress/BUILD.bazel
new file mode 100644
index 000000000..a298042eb
--- /dev/null
+++ b/packages/circular-progress/BUILD.bazel
@@ -0,0 +1,24 @@
+load(
+ "//tools:defaults.bzl",
+ "ng_module",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+ng_module(
+ name = "circular-progress",
+ srcs = glob(
+ ["**/*.ts"],
+ exclude = [
+ "**/*.spec.ts",
+ ],
+ ),
+ assets = glob(["**/*.html"]),
+ module_name = "@angular-mdc/web/circular-progress",
+ deps = [
+ "//packages/base",
+ "@npm//@angular/cdk",
+ "@npm//@material/circular-progress",
+ "@npm//@material/progress-indicator",
+ ],
+)
diff --git a/packages/circular-progress/circular-progress-large.html b/packages/circular-progress/circular-progress-large.html
new file mode 100644
index 000000000..26272d5b1
--- /dev/null
+++ b/packages/circular-progress/circular-progress-large.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/circular-progress/circular-progress-medium.html b/packages/circular-progress/circular-progress-medium.html
new file mode 100644
index 000000000..22241914d
--- /dev/null
+++ b/packages/circular-progress/circular-progress-medium.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/circular-progress/circular-progress-small.html b/packages/circular-progress/circular-progress-small.html
new file mode 100644
index 000000000..559c493fc
--- /dev/null
+++ b/packages/circular-progress/circular-progress-small.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/circular-progress/circular-progress.html b/packages/circular-progress/circular-progress.html
new file mode 100644
index 000000000..9f15a23bf
--- /dev/null
+++ b/packages/circular-progress/circular-progress.html
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/packages/circular-progress/circular-progress.ts b/packages/circular-progress/circular-progress.ts
new file mode 100644
index 000000000..a6017526e
--- /dev/null
+++ b/packages/circular-progress/circular-progress.ts
@@ -0,0 +1,170 @@
+import {
+ AfterViewInit,
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ ElementRef,
+ Input,
+ OnChanges,
+ SimpleChanges,
+ ViewEncapsulation,
+} from '@angular/core';
+import {Platform} from '@angular/cdk/platform';
+import {coerceBooleanProperty, coerceNumberProperty} from '@angular/cdk/coercion';
+import {MDCComponent} from '@angular-mdc/web/base';
+import {MDCProgressIndicator} from '@material/progress-indicator/component';
+import {MDCCircularProgressFoundation, MDCCircularProgressAdapter} from '@material/circular-progress';
+
+@Component({
+ selector: 'mdc-circular-progress-large',
+ exportAs: 'mdcCircularProgressLarge',
+ templateUrl: 'circular-progress-large.html',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class MdcCircularProgressLarge {
+ @Input() determinate: boolean = false;
+
+ constructor(public elementRef: ElementRef) {}
+}
+
+@Component({
+ selector: 'mdc-circular-progress-medium',
+ exportAs: 'mdcCircularProgressMedium',
+ templateUrl: 'circular-progress-medium.html',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class MdcCircularProgressMedium {
+ @Input() determinate: boolean = false;
+
+ constructor(public elementRef: ElementRef) {}
+}
+
+@Component({
+ selector: 'mdc-circular-progress-small',
+ exportAs: 'mdcCircularProgressSmall',
+ templateUrl: 'circular-progress-small.html',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class MdcCircularProgressSmall {
+ determinate: boolean = false;
+
+ constructor(public elementRef: ElementRef) {}
+}
+
+@Component({
+ selector: 'mdc-circular-progress',
+ exportAs: 'mdcCircularProgress',
+ host: {
+ 'role': 'progressbar',
+ 'class': 'mdc-circular-progress',
+ '[class.mdc-circular-progress--large]': 'size == "large"',
+ '[class.mdc-circular-progress--medium]': 'size == "medium"',
+ '[class.mdc-circular-progress--small]': 'size == "small"',
+ '[attr.aria-label]': 'label',
+ 'aria-valuemin': '0',
+ 'aria-valuemax': '100'
+ },
+ templateUrl: 'circular-progress.html',
+ encapsulation: ViewEncapsulation.None,
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class MdcCircularProgress extends MDCComponent
+ implements MDCProgressIndicator, OnChanges, AfterViewInit {
+ _root!: Element;
+
+ private _initialized: boolean = false;
+
+ /* Label indicating how the progress bar should be announced to the user. */
+ @Input() label?: string = undefined;
+
+ @Input()
+ get progress(): number {
+ return this._progress;
+ }
+ set progress(value: number) {
+ this._progress = coerceNumberProperty(value);
+ }
+ private _progress = 0;
+
+ @Input()
+ get determinate(): boolean {
+ return this._determinate;
+ }
+ set determinate(value: boolean) {
+ this._determinate = coerceBooleanProperty(value);
+ }
+ private _determinate = false;
+
+ private _determinateCircle!: HTMLElement;
+
+ @Input() size: 'large' | 'medium' | 'small' = 'large';
+
+ getDefaultFoundation() {
+ const adapter: MDCCircularProgressAdapter = {
+ addClass: (className: string) => this._root.classList.add(className),
+ hasClass: (className: string) => this._root.classList.contains(className),
+ removeClass: (className: string) => this._root.classList.remove(className),
+ removeAttribute: (name: string) => this._root.removeAttribute(name),
+ setAttribute: (name: string, value: string) => this._root.setAttribute(name, value),
+ setDeterminateCircleAttribute: (attributeName: string, value: string) =>
+ this._determinateCircle?.setAttribute(attributeName, value),
+ getDeterminateCircleAttribute: (attributeName: string) =>
+ this._determinateCircle?.getAttribute(attributeName)
+ };
+ return new MDCCircularProgressFoundation(adapter);
+ }
+ constructor(
+ private _platform: Platform,
+ private _changeDetectorRef: ChangeDetectorRef,
+ public elementRef: ElementRef) {
+ super(elementRef);
+
+ this._root = this.elementRef.nativeElement;
+ }
+
+ ngAfterViewInit(): void {
+ if (this._platform.isBrowser) {
+ this._initialized = true;
+ this._determinateCircle =
+ this._root.querySelector(MDCCircularProgressFoundation.strings.DETERMINATE_CIRCLE_SELECTOR) as HTMLElement;
+
+ this._foundation.init();
+ this._syncProgressWithFoundation();
+ this._syncDeterminateWithFoundation();
+
+ this._changeDetectorRef.markForCheck();
+ }
+ }
+
+ ngOnChanges(changes: SimpleChanges) {
+ if (!this._initialized) {
+ return;
+ }
+
+ if (changes['progress']) {
+ this._syncProgressWithFoundation();
+ }
+ if (changes['determinate']) {
+ this._syncDeterminateWithFoundation();
+ }
+ }
+
+ open(): void {
+ this._foundation.open();
+ }
+
+ close(): void {
+ this._foundation.close();
+ }
+
+ private _syncProgressWithFoundation(): void {
+ this._foundation.setProgress(this.progress);
+ }
+
+ private _syncDeterminateWithFoundation(): void {
+ this._foundation.setDeterminate(this.determinate);
+ }
+}
diff --git a/packages/circular-progress/index.ts b/packages/circular-progress/index.ts
new file mode 100644
index 000000000..7e1a213e3
--- /dev/null
+++ b/packages/circular-progress/index.ts
@@ -0,0 +1 @@
+export * from './public-api';
diff --git a/packages/circular-progress/module.ts b/packages/circular-progress/module.ts
new file mode 100644
index 000000000..824b69a4d
--- /dev/null
+++ b/packages/circular-progress/module.ts
@@ -0,0 +1,23 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+
+import {
+ MdcCircularProgress,
+ MdcCircularProgressLarge,
+ MdcCircularProgressMedium,
+ MdcCircularProgressSmall,
+} from './circular-progress';
+
+const PROGRESS_DECLARATIONS = [
+ MdcCircularProgress,
+ MdcCircularProgressLarge,
+ MdcCircularProgressMedium,
+ MdcCircularProgressSmall,
+];
+
+@NgModule({
+ imports: [CommonModule],
+ exports: [PROGRESS_DECLARATIONS],
+ declarations: [PROGRESS_DECLARATIONS]
+})
+export class MdcCircularProgressModule { }
diff --git a/packages/circular-progress/public-api.ts b/packages/circular-progress/public-api.ts
new file mode 100644
index 000000000..ea4345ea2
--- /dev/null
+++ b/packages/circular-progress/public-api.ts
@@ -0,0 +1,2 @@
+export * from './module';
+export * from './circular-progress';
diff --git a/packages/config.bzl b/packages/config.bzl
index 4507824de..40e5d9ec3 100644
--- a/packages/config.bzl
+++ b/packages/config.bzl
@@ -4,6 +4,7 @@ entryPoints = [
"card",
"checkbox",
"chips",
+ "circular-progress",
"data-table",
"dialog",
"dom",
diff --git a/packages/mdc_require_config.js b/packages/mdc_require_config.js
index e7c033786..846dce383 100644
--- a/packages/mdc_require_config.js
+++ b/packages/mdc_require_config.js
@@ -7,6 +7,7 @@ require.config({
'@material/base': '/base/npm/node_modules/@material/base/dist/mdc.base',
'@material/checkbox': '/base/npm/node_modules/@material/checkbox/dist/mdc.checkbox',
'@material/chips': '/base/npm/node_modules/@material/chips/dist/mdc.chips',
+ '@material/circular-progress': '/base/npm/node_modules/@material/circular-progress/dist/mdc.circularProgress',
'@material/data-table': '/base/npm/node_modules/@material/data-table/dist/mdc.dataTable',
'@material/dialog': '/base/npm/node_modules/@material/dialog/dist/mdc.dialog',
'@material/dom': '/base/npm/node_modules/@material/dom/dist/mdc.dom',
diff --git a/rollup-globals.bzl b/rollup-globals.bzl
index 3a3312019..fbd0a8382 100644
--- a/rollup-globals.bzl
+++ b/rollup-globals.bzl
@@ -40,6 +40,7 @@ ROLLUP_GLOBALS = {
"@material/base": "mdc.base",
"@material/checkbox": "mdc.checkbox",
"@material/chips": "mdc.chips",
+ "@material/circular-progress": "mdc.circularProgress",
"@material/dialog": "mdc.dialog",
"@material/data-table": "mdc.dataTable",
"@material/drawer": "mdc.drawer",
diff --git a/tools/postinstall/apply-patches.js b/tools/postinstall/apply-patches.js
index 7e14c8275..677536c45 100644
--- a/tools/postinstall/apply-patches.js
+++ b/tools/postinstall/apply-patches.js
@@ -96,7 +96,7 @@ searchAndReplace(
'node_modules/@angular/bazel/src/ng_module.bzl');
// Workaround for: https://github.com/bazelbuild/rules_nodejs/issues/1208.
-applyPatch(path.join(__dirname, './manifest_externs_hermeticity.patch'));
+// applyPatch(path.join(__dirname, './manifest_externs_hermeticity.patch'));
try {
// Temporary patch pre-req for https://github.com/angular/angular/pull/36333.
diff --git a/tools/system-config-tmpl.js b/tools/system-config-tmpl.js
index ade973313..686b01459 100644
--- a/tools/system-config-tmpl.js
+++ b/tools/system-config-tmpl.js
@@ -37,6 +37,7 @@ var pathMapping = {
'@material/base': 'node:@material/base/dist/mdc.base.js',
'@material/checkbox': 'node:@material/checkbox/dist/mdc.checkbox.js',
'@material/chips': 'node:@material/chips/dist/mdc.chips.js',
+ '@material/circular-progress': 'node:@material/circular-progress/dist/mdc.circularProgress.js',
'@material/data-table': 'node:@material/data-table/dist/mdc.dataTable.js',
'@material/dialog': 'node:@material/dialog/dist/mdc.dialog.js',
'@material/dom': 'node:@material/dom/dist/mdc.dom.js',
diff --git a/yarn.lock b/yarn.lock
index 01e8ff78f..8909ac060 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1777,7 +1777,6 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-electron-to-chromium@^1.3.390:
version "1.3.406"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.406.tgz#d4b8f8c9f7405dddbbb646d6b15042cd7c1e6e61"
integrity sha512-bx8vBZoEbhsMmwEZIj2twzfhFoKKZlSLQiENhqgc5/FdAj4/UHEzAri42OTSFA5+0agLR03ReTvIms2dfZ7/Ew==