diff --git a/.angular-cli.json b/.angular-cli.json
index 5dc34e7..e3260d1 100644
--- a/.angular-cli.json
+++ b/.angular-cli.json
@@ -18,8 +18,8 @@
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
- "../node_modules/bootstrap/dist/css/bootstrap.min.css",
- "styles.css"
+ "my-theme.scss",
+ "styles.scss"
],
"scripts": [],
"environmentSource": "environments/environment.ts",
diff --git a/e2e/app.e2e-spec.ts b/e2e/app.e2e-spec.ts
index f6d3547..fcc4164 100644
--- a/e2e/app.e2e-spec.ts
+++ b/e2e/app.e2e-spec.ts
@@ -22,7 +22,7 @@ describe('d3-ng2-demo App', function () {
it('should have one svg with initial dimensions ' +
initialDragZoom2Dimensions.width + 'x' + initialDragZoom2Dimensions.height +
' in app-drag-zoom-2 component', () => {
- let svg = page.getComponentElement('app-drag-zoom-2', 'svg');
+ const svg = page.getComponentElement('app-drag-zoom-2', 'svg');
expect(svg.count()).toEqual(1, 'Incorrect number of elements');
expect(svg.first().getAttribute('width')).toEqual(initialDragZoom2Dimensions.width + '', 'Incorrect width.');
expect(svg.first().getAttribute('height')).toEqual(initialDragZoom2Dimensions.height + '', 'Incorrect height.');
@@ -32,13 +32,13 @@ describe('d3-ng2-demo App', function () {
it('should resize the layout of the Drag & Zoom II visual to '
+ resizedDragZoom2Dimensions.width + 'x' + resizedDragZoom2Dimensions.height +
' after pressing "large" button', () => {
- let button = page.getLayoutButton('large');
+ const button = page.getLayoutButton('large');
expect(button.count()).toEqual(1, 'Incorrect number of "large" buttons');
button.first().click();
- let svg = page.getComponentElement('app-drag-zoom-2', 'svg');
+ const svg = page.getComponentElement('app-drag-zoom-2', 'svg');
expect(svg.count()).toEqual(1, 'Incorrect number of svg elements');
expect(svg.first().getAttribute('width')).toEqual(resizedDragZoom2Dimensions.width + '', 'Incorrect width.');
expect(svg.first().getAttribute('height')).toEqual(resizedDragZoom2Dimensions.height + '', 'Incorrect height.');
diff --git a/e2e/app.po.ts b/e2e/app.po.ts
index 2e6fb0d..c5e491e 100644
--- a/e2e/app.po.ts
+++ b/e2e/app.po.ts
@@ -11,7 +11,7 @@ export class D3Ng2DemoPage {
}
getLayoutButton(buttonText: string) {
- return element(by.tagName('app-wrapper-drag-zoom-2')).all(by.css('button.layout-' + buttonText));
+ return element(by.tagName('app-wrapper-drag-zoom-2')).all(by.css('mat-button-toggle.layout-' + buttonText));
}
}
diff --git a/karma.conf.js b/karma.conf.js
index 7a01a2a..31a81d8 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -34,6 +34,8 @@ module.exports = function (config) {
flags: ['--no-sandbox']
}
},
+ browserDisconnectTimeout: 20000,
+ browserNoActivityTimeout: 20000,
singleRun: false
});
};
diff --git a/package-lock.json b/package-lock.json
index 16bff97..c980132 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -53,6 +53,14 @@
"tslib": "1.8.1"
}
},
+ "@angular/cdk": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-5.0.4.tgz",
+ "integrity": "sha512-6IKDOhDrfKdywTZNTWZbM1O8Q3cTi7uIOAyFC9sXitg0JUy2SHms0UY9FdW32BABIsZp692ofMCMdMPjHDjwwA==",
+ "requires": {
+ "tslib": "1.8.1"
+ }
+ },
"@angular/cli": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.6.4.tgz",
@@ -163,6 +171,14 @@
"tslib": "1.8.1"
}
},
+ "@angular/flex-layout": {
+ "version": "2.0.0-beta.12",
+ "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-2.0.0-beta.12.tgz",
+ "integrity": "sha512-QTOKZxehYTh8fj64V/pNVWNbfNtebSbssyMIXiGJuHTzfyF7GYdRmtjoR2pNpllycz3rE5NYX77EB140Y6BCnw==",
+ "requires": {
+ "tslib": "1.8.1"
+ }
+ },
"@angular/forms": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.2.0.tgz",
@@ -185,6 +201,14 @@
"integrity": "sha512-Yj/y5XrBBXbtwnZ6HJOBl/0XS/JBvVlHb1UWw5MIrsc81k7/eFiRAIKzmGpAba+Sw0G0dO22ABZ4yJjAMsML6A==",
"dev": true
},
+ "@angular/material": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-5.0.4.tgz",
+ "integrity": "sha512-xrGYPHOlNXpPkventLAvZyTjfCo2A8ZfdyJEHNR4LhFWIjw3ilwb1ihNv4dy/qG56g8L4AwQ2cONxQ0YyZfcWg==",
+ "requires": {
+ "tslib": "1.8.1"
+ }
+ },
"@angular/platform-browser": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.2.0.tgz",
@@ -1215,11 +1239,6 @@
"hoek": "2.16.3"
}
},
- "bootstrap": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz",
- "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E="
- },
"brace-expansion": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
diff --git a/package.json b/package.json
index 152c8e1..7fd951e 100644
--- a/package.json
+++ b/package.json
@@ -28,15 +28,17 @@
},
"dependencies": {
"@angular/animations": "^5.1.0",
+ "@angular/cdk": "^5.0.4",
"@angular/common": "^5.1.0",
"@angular/compiler": "^5.1.0",
"@angular/core": "^5.1.0",
+ "@angular/flex-layout": "^2.0.0-beta.12",
"@angular/forms": "^5.1.0",
"@angular/http": "^5.1.0",
+ "@angular/material": "^5.0.4",
"@angular/platform-browser": "^5.1.0",
"@angular/platform-browser-dynamic": "^5.1.0",
"@angular/router": "^5.1.0",
- "bootstrap": "3.3.7",
"core-js": "^2.4.1",
"d3-ng2-service": "1.23.3",
"rxjs": "^5.5.2",
diff --git a/src/_extra-colors.scss b/src/_extra-colors.scss
new file mode 100644
index 0000000..b2609b5
--- /dev/null
+++ b/src/_extra-colors.scss
@@ -0,0 +1,187 @@
+@import '~@angular/material/theming';
+
+@mixin extra-color-classes($theme) {
+ $background: map-get($theme, background);
+ $foreground: map-get($theme, foreground);
+ $accent: map-get($theme, accent);
+ $primary: map-get($theme, primary);
+ $warn: map-get($theme, warn);
+
+ .extra-code {
+ color: mat-color($accent, darker);
+ background-color: mat-color($accent, lighter);
+ }
+
+ .extra-text {
+ color: mat-color($foreground, text);
+ }
+
+ .extra-divider {
+ color: mat-color($foreground, divider);
+ }
+
+ .extra-hint-text {
+ color: mat-color($foreground, hint-text);
+ }
+
+ .extra-secondary-text {
+ color: mat-color($foreground, secondary-text);
+ }
+
+ // Primary Colors ---------------------------------------------------
+
+ .extra-primary-default {
+ color: mat-color($primary, default);
+ }
+
+ .extra-primary-lighter {
+ color: mat-color($primary, lighter);
+ }
+
+ .extra-primary-darker {
+ color: mat-color($primary, darker);
+ }
+
+ .extra-primary-default-bg {
+ background-color: mat-color($primary, default-contrast);
+ }
+
+ .extra-primary-lighter-bg {
+ background-color: mat-color($primary, lighter-contrast);
+ }
+
+ .extra-primary-darker-bg {
+ background-color: mat-color($primary, darker-contrast);
+ }
+
+ // Primary Colors Inverted ---------------------------------------------------
+
+ .extra-inverted-primary-default {
+ color: mat-color($primary, default-contrast);
+ }
+
+ .extra-inverted-primary-lighter {
+ color: mat-color($primary, lighter-contrast);
+ }
+
+ .extra-inverted-primary-darker {
+ color: mat-color($primary, darker-contrast);
+ }
+
+ .extra-inverted-primary-default-bg {
+ background-color: mat-color($primary);
+ }
+
+ .extra-inverted-primary-lighter-bg {
+ background-color: mat-color($primary, lighter);
+ }
+
+ .extra-inverted-primary-darker-bg {
+ background-color: mat-color($primary, darker);
+ }
+
+ // Accent Colors ---------------------------------------------------
+
+ .extra-accent-default {
+ color: mat-color($accent, default);
+ }
+
+ .extra-accent-lighter {
+ color: mat-color($accent, lighter);
+ }
+
+ .extra-accent-darker {
+ color: mat-color($accent, darker);
+ }
+
+ .extra-accent-default-bg {
+ background-color: mat-color($accent, default-contrast);
+ }
+
+ .extra-accent-lighter-bg {
+ background-color: mat-color($accent, lighter-contrast);
+ }
+
+ .extra-accent-darker-bg {
+ background-color: mat-color($accent, darker-contrast);
+ }
+
+ // Accent Colors Inverted ---------------------------------------------------
+
+ .extra-inverted-accent-default {
+ color: mat-color($accent, default-contrast);
+ }
+
+ .extra-inverted-accent-lighter {
+ color: mat-color($accent, lighter-contrast);
+ }
+
+ .extra-inverted-accent-darker {
+ color: mat-color($accent, darker-contrast);
+ }
+
+ .extra-inverted-accent-default-bg {
+ background-color: mat-color($accent);
+ }
+
+ .extra-inverted-accent-lighter-bg {
+ background-color: mat-color($accent, lighter);
+ }
+
+ .extra-inverted-accent-darker-bg {
+ background-color: mat-color($accent, darker);
+ }
+
+ // Warn Colors ---------------------------------------------------
+
+ .extra-warn-default {
+ color: mat-color($warn, default);
+ }
+
+ .extra-warn-lighter {
+ color: mat-color($warn, lighter);
+ }
+
+ .extra-warn-darker {
+ color: mat-color($warn, darker);
+ }
+
+ .extra-warn-default-bg {
+ background-color: mat-color($warn, default-contrast);
+ }
+
+ .extra-warn-lighter-bg {
+ background-color: mat-color($warn, lighter-contrast);
+ }
+
+ .extra-warn-darker-bg {
+ background-color: mat-color($warn, darker-contrast);
+ }
+
+ // Warn Colors Inverted ---------------------------------------------------
+
+ .extra-inverted-warn-default {
+ color: mat-color($warn, default-contrast);
+ }
+
+ .extra-inverted-warn-lighter {
+ color: mat-color($warn, lighter-contrast);
+ }
+
+ .extra-inverted-warn-darker {
+ color: mat-color($warn, darker-contrast);
+ }
+
+ .extra-inverted-warn-default-bg {
+ background-color: mat-color($warn);
+ }
+
+ .extra-inverted-warn-lighter-bg {
+ background-color: mat-color($warn, lighter);
+ }
+
+ .extra-inverted-warn-darker-bg {
+ background-color: mat-color($warn, darker);
+ }
+
+}
diff --git a/src/app/app.component.css b/src/app/app.component.css
index b402a32..38b6cc8 100644
--- a/src/app/app.component.css
+++ b/src/app/app.component.css
@@ -1,18 +1,15 @@
-div.jumbotron {
- background-color: rgb(230, 230, 255);
+.spacer {
+ flex: 1 1 auto;
}
-div.jumbotron p {
- font-size: 14px;
+.splash-image {
+ max-height: 400px;
}
-div.jumbotron img {
- max-height: 400px;
- margin-left: auto;
- margin-right: auto;
+.text-justify p {
+ text-align: justify;
}
-footer {
- background-color: #222;
- color: #eee;
+.text-center p {
+ text-align: center;
}
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 19f08ee..123e8f8 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,113 +1,124 @@
-
+
+
+ {{title}}
+
+
+
+
+ Github
+
+
+
-
+
-
-
Reusable Visual Power?
-
Fuse D3 and Angular in TypeScript (A Demo)
-
-
-
-
Perfect Storm
-
-
- Ever wondered, how to build modern web apps with reusable, interactive data visualization components?
-
-
- The latest incarnation of D3 is getting you excited about new destinations.
-
-
- Angular 2 arrived on the tarmac and has since been rolled into a stable release management cycle.
-
-
- TypeScript has become the fuel that lets you develop complex solutions at scale.
-
-
- Integrating all three, however, seems as daunting as taking off in the perfect storm.
-
-
-
-
-
-
-
-
-
Take Flight
-
-
- This Angular demo app and its source code repository are intended to get you started. Rather than trying to be exhaustive
- or writing a lengthy blog post, a select few well-known D3 demo scripts have been adapted to highlight key considerations.
-
-
- Use an Angular Service to inject the power of D3 version 4 into a project.
-
-
- Explore how D3 visualizations can be implemented as Angular components in TypeScript 2.
-
-
- See how a visualization component can change in response to input data changes.
-
-
- Find ways to unit test your D3 components with Karma/Jasmine and check out a worked example end-to-end test using Protractor.
-
-
+
+
+
+
+
+
+
+
+
+
+ Ever wondered, how to build modern web apps with reusable, interactive data visualization components?
+
+
+ The latest incarnation of
+ D3 is getting you excited about new destinations.
+
+
+ Angular 2 arrived on the tarmac and has since been rolled into a stable release management cycle.
+
+
+ TypeScript has become the fuel that lets you develop complex solutions at scale.
+
+
+ Integrating all three, however, seems as daunting as taking off in the perfect storm.
+
-
+
+
+
-
+
+
+
+
+ This Angular demo app and its source code repository are intended to get you started. Rather than trying to be exhaustive
+ or writing a lengthy blog post, a select few well-known D3 demo scripts have been adapted to highlight key considerations.
+
+
+ Use an Angular Service to inject the power of D3 version 4 into a project.
+
+
+ Explore how D3 visualizations can be implemented as Angular components in TypeScript 2.
+
+
+ See how a visualization component can change in response to input data changes.
+
+
+ Find ways to unit test your D3 components with Karma/Jasmine and check out a worked example end-to-end test using Protractor.
+
+
+
+
-
-
-
-
-
-
-
-
Source Code Resources for this App
-
+
-
Demo App Github Repo
-
D3Service Github Repo
+
+
+
-
-
-
-
- Copyright © 2018 Thomas Wanzek.
-
-
- Released under MIT License. For details see:
- https://github.com/tomwanzek/d3-ng2-demo/tree/master/LICENSE
-
+
-
-
+
+
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts
index a5c7c2a..d2fd5c8 100644
--- a/src/app/app.component.spec.ts
+++ b/src/app/app.component.spec.ts
@@ -4,6 +4,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';
+import {
+ MatButtonModule,
+ MatListModule,
+ MatSidenavModule,
+ MatToolbarModule
+} from '@angular/material';
+
+import {
+ FlexLayoutModule
+} from '@angular/flex-layout';
+
import { AppComponent } from './app.component';
let fixture: ComponentFixture
;
@@ -41,6 +52,13 @@ describe('App: D3Ng2Demo', () => {
MockChild1Component,
MockChild2Component,
MockChild3Component
+ ],
+ imports: [
+ MatButtonModule,
+ FlexLayoutModule,
+ MatListModule,
+ MatSidenavModule,
+ MatToolbarModule
]
});
@@ -62,10 +80,10 @@ describe('App: D3Ng2Demo', () => {
});
it(`should render title 'D3 Angular Demo' in a span of class 'navbar-brand'`, () => {
- let debugEl = fixture.debugElement.query(By.css('span.navbar-brand'));
+ const debugEl = fixture.debugElement.query(By.css('span.toolbar-title'));
expect(debugEl).not.toBeNull('Missing.');
if (debugEl) {
- let nativeEl: HTMLSpanElement = debugEl.nativeElement;
+ const nativeEl: HTMLSpanElement = debugEl.nativeElement;
expect(nativeEl.textContent).toContain('D3 Angular Demo');
}
});
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 25221ea..f3ea930 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,5 +1,15 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import {
+ MatButtonModule,
+ MatButtonToggleModule,
+ MatCardModule,
+ MatListModule,
+ MatSidenavModule,
+ MatToolbarModule
+} from '@angular/material';
import { D3Service } from 'd3-ng2-service';
@@ -22,7 +32,15 @@ import { WrapperVoronoiSpirals3Component } from './d3-demos/wrapper-voronoi-spir
WrapperVoronoiSpirals3Component
],
imports: [
- BrowserModule
+ BrowserModule,
+ BrowserAnimationsModule,
+ FlexLayoutModule,
+ MatButtonModule,
+ MatButtonToggleModule,
+ MatCardModule,
+ MatListModule,
+ MatSidenavModule,
+ MatToolbarModule
],
providers: [
D3Service
diff --git a/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.css b/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.css
index 7c5a8e7..3f14dc6 100644
--- a/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.css
+++ b/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.css
@@ -1,19 +1,5 @@
-div.container {
- background-color: rgb(245, 250, 245);
- margin-top: 10px;
- margin-bottom: 10px;
- border-radius: 10px;
-}
-
-div.col {
- padding-top: 10px;
- padding-bottom: 5px;
-}
-
-h3 {
- border-bottom: 1px solid #337ab7;
- padding-top: 10px;
- margin-bottom: 20px;
+.mat-card {
+ margin: 8px;
}
div.visualization {
@@ -27,3 +13,6 @@ div.visualization {
overflow-x: auto;
}
+.text-justify {
+ text-align: justify;
+}
diff --git a/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.html b/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.html
index 9e41f7e..4a2d6d1 100644
--- a/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.html
+++ b/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.html
@@ -1,60 +1,58 @@
-
-
-
-
-
- Demonstrate how to:
-
-
-
- build an Angular component which uses a D3 service to render to <svg>
, and
-
-
- use D3 version 4 in TypeScript to draw a scatter plot with brush and zoom/pan event handling.
-
-
-
-
-
-
-
Reference
-
- This example is based on Mike Bostock's Brush & Zoom II Block . The original source with its supporting explanation
- can be found by following the link below.
-
-
- Source: Brush & Zoom II Block .
-
-
-
-
D3 Angular Implementation
-
- The implementation is a straightforward Angular component without any inputs. Its template is an <svg>
element with fixed dimensions. The component renders the visualization using the d3
instance provided
- by the injected D3Service
.
-
-
- The D3 component can be embedded into a parent component using the following tag:
-
-
- <app-brush-zoom-2></app-brush-zoom-2>
.
-
-
- The source code for the D3 component can be found at:
-
-
- Brush Zoom II D3 Component .
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Demonstrate how to:
+
+
+
+ build an Angular component which uses a D3 service to render to
+ , and
+
+
+ use D3 version 4 in TypeScript to draw a scatter plot with brush and zoom/pan event handling.
+
+
+
+
+
+
+
+
+ This example is based on Mike Bostock's Brush & Zoom II Block . The original source with its supporting explanation
+ can be found by following the link below.
+
+
+
+ Brush & Zoom II Block
+
+
+
+
+
+ The implementation is a straightforward Angular component without any inputs. Its template is an element with fixed dimensions. The component renders the visualization using the instance provided
+ by the injected .
+
+
+ The D3 component can be embedded into a parent component using the following tag:
+
+
+ .
+
+
+
+ Brush Zoom II D3 Component
+
+
+
-
-
+
+
+
diff --git a/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.spec.ts b/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.spec.ts
index 390d8f3..694d346 100644
--- a/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.spec.ts
+++ b/src/app/d3-demos/wrapper-brush-zoom-2/wrapper-brush-zoom-2.component.spec.ts
@@ -4,6 +4,15 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';
+import {
+ MatCardModule,
+ MatListModule
+} from '@angular/material';
+
+import {
+ FlexLayoutModule
+} from '@angular/flex-layout';
+
import { WrapperBrushZoom2Component } from './wrapper-brush-zoom-2.component';
let fixture: ComponentFixture
;
@@ -23,6 +32,11 @@ describe('Component: WrapperBrushZoom2', () => {
declarations: [
WrapperBrushZoom2Component,
MockChildComponent
+ ],
+ imports: [
+ FlexLayoutModule,
+ MatCardModule,
+ MatListModule
]
});
@@ -40,22 +54,22 @@ describe('Component: WrapperBrushZoom2', () => {
});
- it(`should have a div with class 'container' as its only child HTMLElement`, () => {
+ it(`should have a mat-card element as its only child DOM Element`, () => {
let nativeEls: HTMLCollection | undefined[];
nativeEls = compiled ? compiled.children : [];
expect(nativeEls.length).toBe(1, 'Incorrect number of elements found');
if (nativeEls.length === 1) {
- expect(nativeEls[0].tagName === 'div' || nativeEls[0].tagName === 'DIV').toBeTruthy('Not a "div" element.');
- expect(nativeEls[0].classList.contains('container')).toBeTruthy('Not of class "container".');
+ expect(nativeEls[0].tagName === 'mat-card' || nativeEls[0].tagName === 'MAT-CARD').toBeTruthy('Not a "mat-card" element.');
}
});
- it(`should have heading h3 with text 'Brush & Zoom II'`, () => {
- let nativeEls: NodeListOf | undefined[];
- nativeEls = compiled ? compiled.querySelectorAll('h3') : [];
+ it(`should have headline div with class 'mat-headline' and text content 'Brush & Zoom II'`, () => {
+ let nativeEls: NodeListOf | HTMLDivElement[];
+ // HACK: Using 'as' due to TS issue with querySelectorAll signature in TS 2.5.3
+ nativeEls = compiled ? compiled.querySelectorAll('div.mat-headline') as NodeListOf : [];
expect(nativeEls.length).toBe(1, 'Incorrect number of elements found');
if (nativeEls.length === 1) {
- let nativeEl = nativeEls[0];
+ const nativeEl = nativeEls[0];
expect(nativeEl.textContent).toBe('Brush & Zoom II');
}
});
diff --git a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.css b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.css
index 697c563..4a7c829 100644
--- a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.css
+++ b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.css
@@ -1,19 +1,5 @@
-div.container {
- background-color: rgb(245, 250, 245);
- margin-top: 10px;
- margin-bottom: 10px;
- border-radius: 10px;
-}
-
-div.col {
- padding-top: 10px;
- padding-bottom: 5px;
-}
-
-h3 {
- border-bottom: 1px solid #337ab7;
- padding-top: 10px;
- margin-bottom: 20px;
+.mat-card {
+ margin: 8px;
}
div.visualization {
@@ -26,3 +12,22 @@ div.visualization {
margin: 10px auto 15px auto;
overflow-x: auto;
}
+
+.settings-table th {
+ font-weight: bold;
+ text-align: start;
+ padding: 5px;
+}
+
+.settings-table th.text-center {
+ text-align: center;
+}
+
+.settings-table td {
+ text-align: start;
+ padding: 5px;
+}
+
+.text-justify {
+ text-align: justify;
+}
diff --git a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.html b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.html
index b9873d3..ba70133 100644
--- a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.html
+++ b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.html
@@ -1,111 +1,104 @@
-
-
-
-
-
- Demonstrate how to:
-
-
-
- build an Angular component which uses a D3 service to render to <svg>
,
-
-
- use D3 version 4 in TypeScript to handle drag and zoom/pan events, and
-
-
- use Angular to respond to input changes to a reusable D3 component.
-
-
-
-
-
-
-
Reference
-
- This example is based on Mike Bostock's Drag & Zoom II Block . The original source with its supporting explanation
- can be found by following the link below.
-
-
- Source: Drag & Zoom II Block .
-
-
-
-
D3 Angular Implementation
-
- The implementation is an Angular component with inputs.
-
-
- The component supports inputs controlling key layout determinants: height , width , the radius of the phyllotaxis layout ,
- and the point radius . Its template is a plain <svg>
element.
-
-
- The component renders the visualization using the d3
instance provided by the injected D3Service
.
- When input values change, the visualization is redrawn.
-
-
- The D3 component can be embedded into a parent component using the following tag:
-
-
- <app-drag-zoom-2 [width]="960" [height]="500" [phylloRadius]="10" [pointRadius]="2.5"></app-drag-zoom-2>
.
-
-
- The numeric example inputs above reflect the choices of the reference source. However, in true Angular manner the component
- is reusable and can obtain input values from parent component properties, as shown below.
-
-
- The source code for the D3 component and its parent component can be found at:
-
-
- Drag Zoom II D3 Component .
-
-
- Drag Zoom II Wrapper Parent Component .
-
+
+
+
+
+
+
+
+
+ Demonstrate how to:
+
+
+
+ build an Angular component which uses a D3 service to render to
+ ,
+
+
+ use D3 version 4 in TypeScript to handle drag and zoom/pan events, and
+
+
+ use Angular to respond to input changes to a reusable D3 component.
+
+
+
+
+
+
+
+
+ This example is based on
+ Mike Bostock's Drag & Zoom II Block . The original source with its supporting explanation can be found by
+ following the link below.
+
+
+
+ Drag & Zoom II Block
+
+
+
+
+
+ The implementation is a straightforward Angular component without any inputs. Its template is an
+ element with fixed dimensions. The component renders the visualization using the
+ instance provided by the injected
+ .
+
+
+ The D3 component can be embedded into a parent component using the following tag:
+
+
+ .
+
+
+
+ Brush Zoom II D3 Component
+
+
+
+
-
-
-
-
-
+
+
+
- Choose Layout:
-
-
- {{layout.name}}
-
+
+
+
+ {{layout.name}}
+
+
- Width
+
{{selectedLayout.width}}
- Height
+
{{selectedLayout.height}}
- Radius (Phyllotaxis)
+
{{selectedLayout.phylloRadius}}
- Radius (Point)
+
{{selectedLayout.pointRadius}}
-
-
-
+
+
diff --git a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.spec.ts b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.spec.ts
index ba5e484..806f3d4 100644
--- a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.spec.ts
+++ b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.spec.ts
@@ -8,6 +8,15 @@ import { DragZoom2Component } from '../drag-zoom-2/drag-zoom-2.component';
import { D3Service } from 'd3-ng2-service';
+import {
+ MatButtonToggleModule,
+ MatCardModule,
+ MatListModule
+} from '@angular/material';
+
+import {
+ FlexLayoutModule
+} from '@angular/flex-layout';
let fixture: ComponentFixture;
let component: WrapperDragZoom2Component;
@@ -23,6 +32,12 @@ describe('Component: WrapperDragZoom2', () => {
],
providers: [
D3Service
+ ],
+ imports: [
+ FlexLayoutModule,
+ MatButtonToggleModule,
+ MatCardModule,
+ MatListModule
]
});
@@ -39,22 +54,22 @@ describe('Component: WrapperDragZoom2', () => {
expect(component).toBeTruthy();
});
- it(`should have a div with class 'container' as its only child HTMLElement`, () => {
+ it(`should have a mat-card element as its only child DOM Element`, () => {
let nativeEls: HTMLCollection | undefined[];
nativeEls = compiled ? compiled.children : [];
expect(nativeEls.length).toBe(1, 'Incorrect number of elements found');
if (nativeEls.length === 1) {
- expect(nativeEls[0].tagName === 'div' || nativeEls[0].tagName === 'DIV').toBeTruthy('Not a "div" element.');
- expect(nativeEls[0].classList.contains('container')).toBeTruthy('Not of class "container".');
+ expect(nativeEls[0].tagName === 'mat-card' || nativeEls[0].tagName === 'MAT-CARD').toBeTruthy('Not a "mat-card" element.');
}
});
- it(`should have heading h3 with text 'Drag & Zoom II'`, () => {
- let nativeEls: NodeListOf | undefined[];
- nativeEls = compiled ? compiled.querySelectorAll('h3') : [];
+ it(`should have headline div with class 'mat-headline' and text content 'Drag & Zoom II'`, () => {
+ let nativeEls: NodeListOf | HTMLDivElement[];
+ // HACK: Using 'as' due to TS issue with querySelectorAll signature in TS 2.5.3
+ nativeEls = compiled ? compiled.querySelectorAll('div.mat-headline') as NodeListOf : [];
expect(nativeEls.length).toBe(1, 'Incorrect number of elements found');
if (nativeEls.length === 1) {
- let nativeEl = nativeEls[0];
+ const nativeEl = nativeEls[0];
expect(nativeEl.textContent).toBe('Drag & Zoom II');
}
});
diff --git a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.ts b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.ts
index 83bd784..c98570d 100644
--- a/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.ts
+++ b/src/app/d3-demos/wrapper-drag-zoom-2/wrapper-drag-zoom-2.component.ts
@@ -1,6 +1,5 @@
import { Component, Input, OnInit } from '@angular/core';
-
export interface DragZoom2Layout {
name: string;
label: string;
@@ -38,6 +37,7 @@ export class WrapperDragZoom2Component implements OnInit {
pointRadius: 4
}
];
+ public selectedLayoutName = 'small';
ngOnInit() {
if (this.selectedLayout === undefined) {
@@ -49,5 +49,4 @@ export class WrapperDragZoom2Component implements OnInit {
this.selectedLayout = layout;
}
-
}
diff --git a/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.css b/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.css
index 697c563..3f14dc6 100644
--- a/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.css
+++ b/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.css
@@ -1,19 +1,5 @@
-div.container {
- background-color: rgb(245, 250, 245);
- margin-top: 10px;
- margin-bottom: 10px;
- border-radius: 10px;
-}
-
-div.col {
- padding-top: 10px;
- padding-bottom: 5px;
-}
-
-h3 {
- border-bottom: 1px solid #337ab7;
- padding-top: 10px;
- margin-bottom: 20px;
+.mat-card {
+ margin: 8px;
}
div.visualization {
@@ -26,3 +12,7 @@ div.visualization {
margin: 10px auto 15px auto;
overflow-x: auto;
}
+
+.text-justify {
+ text-align: justify;
+}
diff --git a/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.html b/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.html
index 4ea5d0c..45608af 100644
--- a/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.html
+++ b/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.html
@@ -1,60 +1,61 @@
-
-
-
-
Voronoi Spirals III
-
-
-
-
-
- Demonstrate how to:
-
-
-
- build an Angular component which uses a D3 service to render to <canvas>
,
-
-
- use D3 version 4 in TypeScript for Voronoi polygons.
-
-
-
-
-
-
-
Reference
-
- This example is based on Mike Bostock's Voronoi Spirals III Block . The original source with its supporting
- explanation can be found by following the link below.
-
-
- Source: Voronoi Spirals III Block .
-
-
-
-
D3 Angular Implementation
-
- The implementation is a straightforward Angular component without any inputs. Its template is a <canvas>
element with fixed dimensions. The component renders the visualization using the d3
instance provided
- by the injected D3Service
.
-
-
- The D3 component can be embedded into a parent component using the following tag:
-
-
- <app-voronoi-spirals-3></app-voronoi-spirals-3>
.
-
-
- The source code for the D3 component can be found at:
-
-
- Voronoi Spirals III D3 Component .
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ Demonstrate how to:
+
+
+
+ build an Angular component which uses a D3 service to render to
+ ,
+
+
+ use D3 version 4 in TypeScript for Voronoi polygons.
+
+
+
+
+
+
+
+
+ This example is based on
+ Mike Bostock's Voronoi Spirals III Block . The original source with its supporting explanation can be found
+ by following the link below.
+
+
+
+ Voronoi Spirals III Block
+
+
+
+
+
+ The implementation is a straightforward Angular component without any inputs. Its template is a
+ element with fixed dimensions. The component renders the visualization using the
+ instance provided by the injected
+ .
+
+
+ The D3 component can be embedded into a parent component using the following tag:
+
+
+ .
+
+
+
+ Voronoi Spirals III D3 Component
+
+
+
-
-
+
+
+
diff --git a/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.spec.ts b/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.spec.ts
index 1669739..314c92d 100644
--- a/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.spec.ts
+++ b/src/app/d3-demos/wrapper-voronoi-spirals-3/wrapper-voronoi-spirals-3.component.spec.ts
@@ -4,6 +4,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';
+import {
+ MatCardModule,
+ MatListModule
+} from '@angular/material';
+
+import {
+ FlexLayoutModule
+} from '@angular/flex-layout';
+
+
import { WrapperVoronoiSpirals3Component } from './wrapper-voronoi-spirals-3.component';
let fixture: ComponentFixture
;
@@ -14,7 +24,7 @@ let compiled: HTMLElement | null;
selector: 'app-voronoi-spirals-3',
template: ` `
})
-class MockChildComponent {};
+class MockChildComponent {}
describe('Component: WrapperVoronoiSpirals3', () => {
@@ -24,6 +34,11 @@ describe('Component: WrapperVoronoiSpirals3', () => {
declarations: [
WrapperVoronoiSpirals3Component,
MockChildComponent
+ ],
+ imports: [
+ FlexLayoutModule,
+ MatCardModule,
+ MatListModule
]
});
@@ -40,22 +55,22 @@ describe('Component: WrapperVoronoiSpirals3', () => {
expect(component).toBeTruthy();
});
- it(`should have a div with class 'container' as its only child HTMLElement`, () => {
+ it(`should have a mat-card element as its only child DOM Element`, () => {
let nativeEls: HTMLCollection | undefined[];
nativeEls = compiled ? compiled.children : [];
expect(nativeEls.length).toBe(1, 'Incorrect number of elements found');
if (nativeEls.length === 1) {
- expect(nativeEls[0].tagName === 'div' || nativeEls[0].tagName === 'DIV').toBeTruthy('Not a "div" element.');
- expect(nativeEls[0].classList.contains('container')).toBeTruthy('Not of class "container".');
+ expect(nativeEls[0].tagName === 'mat-card' || nativeEls[0].tagName === 'MAT-CARD').toBeTruthy('Not a "mat-card" element.');
}
});
- it(`should have heading h3 with text 'Voronoi Spirals III'`, () => {
- let nativeEls: NodeListOf | undefined[];
- nativeEls = compiled ? compiled.querySelectorAll('h3') : [];
+ it(`should have headline div with class 'mat-headline' and text content 'Voronoi Spirals III'`, () => {
+ let nativeEls: NodeListOf | HTMLDivElement[];
+ // HACK: Using 'as' due to TS issue with querySelectorAll signature in TS 2.5.3
+ nativeEls = compiled ? compiled.querySelectorAll('div.mat-headline') as NodeListOf : [];
expect(nativeEls.length).toBe(1, 'Incorrect number of elements found');
if (nativeEls.length === 1) {
- let nativeEl = nativeEls[0];
+ const nativeEl = nativeEls[0];
expect(nativeEl.textContent).toBe('Voronoi Spirals III');
}
});
diff --git a/src/assets/GitHub-Mark-32px.png b/src/assets/GitHub-Mark-32px.png
new file mode 100644
index 0000000..8b25551
Binary files /dev/null and b/src/assets/GitHub-Mark-32px.png differ
diff --git a/src/assets/GitHub-Mark-Light-32px.png b/src/assets/GitHub-Mark-Light-32px.png
new file mode 100644
index 0000000..628da97
Binary files /dev/null and b/src/assets/GitHub-Mark-Light-32px.png differ
diff --git a/src/index.html b/src/index.html
index 19bbf75..918e3bf 100644
--- a/src/index.html
+++ b/src/index.html
@@ -12,15 +12,7 @@
-
+ Loading...
diff --git a/src/my-theme.scss b/src/my-theme.scss
new file mode 100644
index 0000000..9aa5bd7
--- /dev/null
+++ b/src/my-theme.scss
@@ -0,0 +1,14 @@
+@import '~@angular/material/theming';
+@import './_extra-colors.scss';
+
+@include mat-core();
+
+$sharp-light-primary: mat-palette($mat-indigo, 400, 200, 800);
+$sharp-light-accent: mat-palette($mat-pink, A200, 100, A700);
+
+$sharp-light-warn: mat-palette($mat-red);
+
+$sharp-light-theme: mat-light-theme($sharp-light-primary, $sharp-light-accent, $sharp-light-warn);
+
+@include angular-material-theme($sharp-light-theme);
+@include extra-color-classes($sharp-light-theme);
diff --git a/src/styles.css b/src/styles.css
deleted file mode 100644
index 63c15f5..0000000
--- a/src/styles.css
+++ /dev/null
@@ -1,6 +0,0 @@
-/* You can add global styles to this file, and also import other style files */
-
-body {
- background-color: slateblue;
- padding-top: 70px;
-}
diff --git a/src/styles.scss b/src/styles.scss
new file mode 100644
index 0000000..4dd4a0d
--- /dev/null
+++ b/src/styles.scss
@@ -0,0 +1,11 @@
+html, body {
+ display: flex;
+ flex-direction: column;
+ font-family: Roboto, Arial, sans-serif;
+ margin: 0;
+ height: 100%;
+}
+
+.uppercase {
+ text-transform: uppercase;
+}