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 @@ +
+

Large

+
+ + +
+
+ +
+

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==