From 56ce1639c57804f6263dfa4bd928e90848cadbbd Mon Sep 17 00:00:00 2001 From: Katja Bregenzer Date: Thu, 14 Feb 2019 16:24:37 +0100 Subject: [PATCH] feat(limel-chart): add component fix #287 --- package-lock.json | 42 ++++++- package.json | 2 + src/components/chart/chart.mdx | 35 ++++++ src/components/chart/chart.tsx | 124 ++++++++++++++++++++ src/examples/chart/chart-bar.tsx | 43 +++++++ src/examples/chart/chart-custom-colors.tsx | 55 +++++++++ src/examples/chart/chart-default-colors.tsx | 63 ++++++++++ src/examples/chart/chart-line.tsx | 45 +++++++ 8 files changed, 407 insertions(+), 2 deletions(-) create mode 100644 src/components/chart/chart.mdx create mode 100644 src/components/chart/chart.tsx create mode 100644 src/examples/chart/chart-bar.tsx create mode 100644 src/examples/chart/chart-custom-colors.tsx create mode 100644 src/examples/chart/chart-default-colors.tsx create mode 100644 src/examples/chart/chart-line.tsx diff --git a/package-lock.json b/package-lock.json index 88d6c96719..0b96329a10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3084,6 +3084,12 @@ "loader-utils": "^1.1.0" } }, + "@types/chart.js": { + "version": "2.7.45", + "resolved": "http://npm.lundalogik.com:4873/@types%2fchart.js/-/chart.js-2.7.45.tgz", + "integrity": "sha512-4uY+gN+ryPCX6DwgDN0a726mThl7MKunobzQh4Z8KX+19bvjtDy1tNSamOfEFDBiGcTEishIjAdPFI83B9vQgA==", + "dev": true + }, "@types/jest": { "version": "23.3.13", "resolved": "http://npm.lundalogik.com:4873/@types%2fjest/-/jest-23.3.13.tgz", @@ -4871,6 +4877,39 @@ "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==", "dev": true }, + "chart.js": { + "version": "2.7.3", + "resolved": "http://npm.lundalogik.com:4873/chart.js/-/chart.js-2.7.3.tgz", + "integrity": "sha512-3+7k/DbR92m6BsMUYP6M0dMsMVZpMnwkUyNSAbqolHKsbIzH2Q4LWVEHHYq7v0fmEV8whXE0DrjANulw9j2K5g==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.2.0", + "resolved": "http://npm.lundalogik.com:4873/chartjs-color/-/chartjs-color-2.2.0.tgz", + "integrity": "sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=", + "requires": { + "chartjs-color-string": "^0.5.0", + "color-convert": "^0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "http://npm.lundalogik.com:4873/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + } + } + }, + "chartjs-color-string": { + "version": "0.5.0", + "resolved": "http://npm.lundalogik.com:4873/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz", + "integrity": "sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==", + "requires": { + "color-name": "^1.0.0" + } + }, "chokidar": { "version": "2.0.3", "resolved": "http://npm.lundalogik.com:4873/chokidar/-/chokidar-2.0.3.tgz", @@ -5368,8 +5407,7 @@ "color-name": { "version": "1.1.1", "resolved": "http://npm.lundalogik.com:4873/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", - "dev": true + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" }, "colors": { "version": "1.0.3", diff --git a/package.json b/package.json index 0712268424..c2f07c91ce 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ }, "dependencies": { "awesome-debounce-promise": "^1.0.0", + "chart.js": "^2.7.3", "flatpickr": "^4.5.2", "jsx-dom": "^6.2.1", "lime-material-components-web": "0.43.1", @@ -58,6 +59,7 @@ "@semantic-release/git": "^7.0.8", "@stencil/core": "^0.18.0", "@stencil/sass": "^0.1.1", + "@types/chart.js": "^2.7.45", "@types/jest": "^23.3.13", "@types/puppeteer": "1.11.2", "commitizen": "^3.0.5", diff --git a/src/components/chart/chart.mdx b/src/components/chart/chart.mdx new file mode 100644 index 0000000000..9c098bedf5 --- /dev/null +++ b/src/components/chart/chart.mdx @@ -0,0 +1,35 @@ +--- +name: Chart +route: /chart +menu: Components +--- + +# Chart + +For detailed documentation of the configuration options, please see https://www.chartjs.org/docs/2.7.3/charts/ + + + +## Examples + +### Using Default Colors + +When using `limel-chart` without colors specified, the chart will default to the Lime brand colors. If there are more datasets than colors, the colors will repeat. + + + +### Using Custom Colors + +Colors can be set using any css color value. The most commonly used will likely be hex-values (e.g. `#ff0000` for red), rgb-values (e.g. `rbg(255, 0, 0)` for red) and rgba-values (e.g. `rgba(255, 0, 0, 0.5)` for red with 50 % transparency). + + + +## Chart Types + +### Bar Chart + + + +### Line Chart + + diff --git a/src/components/chart/chart.tsx b/src/components/chart/chart.tsx new file mode 100644 index 0000000000..b9ad2149cd --- /dev/null +++ b/src/components/chart/chart.tsx @@ -0,0 +1,124 @@ +import { Component, Element, Prop } from '@stencil/core'; +import Chart from 'chart.js'; + +@Component({ + tag: 'limel-chart', + shadow: true, +}) +export class LChart { + /** + * See the Chart.js documentation for [Category Cartesian Axis](https://www.chartjs.org/docs/2.7.3/axes/cartesian/category.html#category-cartesian-axis). + */ + @Prop() + public labels: Array = []; + + /** + * See the Chart.js documentation for your chosen [chart type](https://www.chartjs.org/docs/2.7.3/charts/). + */ + @Prop() + public datasets: Chart.ChartDataSets[] = []; + + @Prop({ reflectToAttr: true }) + public type: Chart.ChartType; + + /** + * See the Chart.js documentation for [Global Configuration](https://www.chartjs.org/docs/2.7.3/configuration/) and for your chosen [chart type](https://www.chartjs.org/docs/2.7.3/charts/). + */ + @Prop() + public options: Chart.ChartOptions = {}; + + @Element() + private element: HTMLElement; + + private chart; + + private defaultColors = [ + '--lime-turquoise', + '--lime-magenta', + '--lime-yellow', + '--lime-green', + '--lime-red', + '--lime-orange', + ]; + + public componentDidLoad() { + const defaultFontColor = this.getPropertyValue('color'); + const defaultFontFamily = this.getPropertyValue('font-family'); + const defaultFontSize = parseInt( + this.getPropertyValue('font-size').replace('px', ''), + 10 + ); + Chart.defaults.global.defaultFontColor = defaultFontColor; + Chart.defaults.global.defaultFontFamily = defaultFontFamily; + Chart.defaults.global.defaultFontSize = defaultFontSize; + + const datasets = this.getDatasetsWithColors(this.type); + + const canvas: HTMLCanvasElement = this.element.shadowRoot.querySelector( + '.chart' + ); + this.chart = new Chart(canvas, { + data: { datasets: datasets, labels: this.labels }, + type: this.type, + options: this.options, + }); + } + + public componentDidUnload() { + this.chart.destroy(); + } + + public render() { + return ( +
+ +
+ ); + } + + private getPropertyValue(propertyName) { + return window + .getComputedStyle(document.body) + .getPropertyValue(propertyName) + .trim(); + } + + private getDatasetsWithColors(chartType: Chart.ChartType) { + return this.datasets.map((dataset, index) => { + if (dataset.backgroundColor || dataset.borderColor) { + return { ...dataset }; + } else { + return this.extendDatasetWithLimeColors( + index, + dataset, + chartType + ); + } + }); + } + + private extendDatasetWithLimeColors(index, dataset, chartType) { + const colorIndex = index % this.defaultColors.length; + const hexColor = this.getPropertyValue(this.defaultColors[colorIndex]); + const rgbColor = this.convertHex(hexColor); + const bgOpacity = chartType === 'bar' ? 1 : 0.2; // tslint:disable-line:no-magic-numbers + + return { + ...dataset, + backgroundColor: rgbColor.replace(')', ',' + bgOpacity + ')'), + borderColor: rgbColor, + }; + } + + private convertHex(hex) { + const rEnd = 2; + const gEnd = 4; + const bEnd = 6; + hex = hex.replace('#', ''); + const r = parseInt(hex.substring(0, rEnd), 16); + const g = parseInt(hex.substring(rEnd, gEnd), 16); + const b = parseInt(hex.substring(gEnd, bEnd), 16); + + return 'rgba(' + r + ',' + g + ',' + b + ')'; + } +} diff --git a/src/examples/chart/chart-bar.tsx b/src/examples/chart/chart-bar.tsx new file mode 100644 index 0000000000..fd5e46ad05 --- /dev/null +++ b/src/examples/chart/chart-bar.tsx @@ -0,0 +1,43 @@ +import { Component } from '@stencil/core'; + +@Component({ + tag: 'limel-example-chart-bar', + shadow: true, +}) +export class ChartBarExample { + private labels = ['Cheese', 'Coffee']; + private datasets = [ + { + label: 'France', + data: [12, 5], // tslint:disable-line:no-magic-numbers + }, + { + label: 'Sweden', + data: [3, 19], // tslint:disable-line:no-magic-numbers + }, + ]; + + private type: Chart.ChartType = 'bar'; + private options = { + scales: { + yAxes: [ + { + ticks: { + beginAtZero: true, + }, + }, + ], + }, + }; + + public render() { + return ( + + ); + } +} diff --git a/src/examples/chart/chart-custom-colors.tsx b/src/examples/chart/chart-custom-colors.tsx new file mode 100644 index 0000000000..1f8b6d2d5f --- /dev/null +++ b/src/examples/chart/chart-custom-colors.tsx @@ -0,0 +1,55 @@ +import { Component } from '@stencil/core'; + +@Component({ + tag: 'limel-example-chart-custom-colors', + shadow: true, +}) +export class ChartColorsExample { + private labels = ['A', 'B']; + private datasets = [ + { + label: 'Using hex-values', + data: [5, 3], // tslint:disable-line:no-magic-numbers + backgroundColor: '#ff0000', + borderColor: '#ff0000', + }, + { + label: 'Semi-transparent background, solid border', + data: [5, 3], // tslint:disable-line:no-magic-numbers + backgroundColor: 'rgba(0, 0, 255, 0.2)', + borderColor: 'rgba(0, 0, 255, 1)', + }, + { + label: 'No color set ', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + { + label: 'No color set', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + ]; + + private type: Chart.ChartType = 'bar'; + private options = { + scales: { + yAxes: [ + { + ticks: { + beginAtZero: true, + }, + }, + ], + }, + }; + + public render() { + return ( + + ); + } +} diff --git a/src/examples/chart/chart-default-colors.tsx b/src/examples/chart/chart-default-colors.tsx new file mode 100644 index 0000000000..8a680c0ba8 --- /dev/null +++ b/src/examples/chart/chart-default-colors.tsx @@ -0,0 +1,63 @@ +import { Component } from '@stencil/core'; + +@Component({ + tag: 'limel-example-chart-default-colors', + shadow: true, +}) +export class ChartDefaultColorsExample { + private labels = ['A', 'B']; + private datasets = [ + { + label: 'Turquoise', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + { + label: 'Magenta', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + { + label: 'Yellow', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + { + label: 'Green', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + { + label: 'Red', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + { + label: 'Orange', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + { + label: 'Repeat', + data: [5, 3], // tslint:disable-line:no-magic-numbers + }, + ]; + + private type: Chart.ChartType = 'bar'; + private options = { + scales: { + yAxes: [ + { + ticks: { + beginAtZero: true, + }, + }, + ], + }, + }; + + public render() { + return ( + + ); + } +} diff --git a/src/examples/chart/chart-line.tsx b/src/examples/chart/chart-line.tsx new file mode 100644 index 0000000000..8f3259f211 --- /dev/null +++ b/src/examples/chart/chart-line.tsx @@ -0,0 +1,45 @@ +import { Component } from '@stencil/core'; + +@Component({ + tag: 'limel-example-chart-line', + shadow: true, +}) +export class ChartLineExample { + private labels = ['January', 'February', 'March', 'April', 'May', 'June']; + private datasets = [ + { + data: [65, 59, 80, 81, 56, 55], // tslint:disable-line:no-magic-numbers + fill: false, + }, + ]; + + private type: Chart.ChartType = 'line'; + private options = { + legend: { display: false }, + elements: { + line: { + tension: 0, // draw straight lines + }, + }, + scales: { + yAxes: [ + { + ticks: { + beginAtZero: true, + }, + }, + ], + }, + }; + + public render() { + return ( + + ); + } +}