├── .ncurc.json ├── doc ├── api.json └── CHANGELOG.md ├── .gitignore ├── packages ├── aurelia-chart │ ├── tsconfig.json │ ├── src │ │ ├── elements │ │ │ ├── chart-element.html │ │ │ └── chart-element.ts │ │ ├── index.ts │ │ ├── attributes │ │ │ └── chart-attribute.ts │ │ └── observers │ │ │ └── model-observer.ts │ ├── tsconfig.build.json │ ├── LICENSE │ └── package.json └── demo │ ├── index.ejs │ ├── index.html │ ├── tsconfig.json │ ├── package.json │ ├── src │ ├── main.ts │ ├── app.html │ └── app.ts │ └── webpack.config.js ├── tsconfig.json ├── .editorconfig ├── tsconfig.build.json ├── LICENSE ├── package.json ├── readme.md └── .eslintrc.js /.ncurc.json: -------------------------------------------------------------------------------- 1 | { 2 | "reject": [] 3 | } 4 | -------------------------------------------------------------------------------- /doc/api.json: -------------------------------------------------------------------------------- 1 | {"classes":[],"methods":[],"properties":[],"events":[]} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | 4 | packages/*/src/*.css 5 | packages/**/api.json 6 | -------------------------------------------------------------------------------- /packages/aurelia-chart/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/aurelia-chart/src/elements/chart-element.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /packages/aurelia-chart/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.build.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "compilerOptions": { 4 | "baseUrl": "./packages", 5 | "paths": { 6 | "aurelia-chart": ["aurelia-chart/src"] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/demo/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Aurelia 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Aurelia 5 | 6 | 7 | 8 |
9 |
Aurelia Chart Example
10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "allowSyntheticDefaultImports": true, 5 | "target": "ES2015", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@aurelia-mdc-web/*": ["../*/src"] 9 | }, 10 | "resolveJsonModule": true, 11 | "noUnusedLocals": false, 12 | "noUnusedParameters": false, 13 | "newLine": "lf" 14 | }, 15 | "exclude": [] 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [node_modules/**/*,dist/**/*] 16 | insert_final_newline = false 17 | indent_style = none 18 | indent_size = none 19 | -------------------------------------------------------------------------------- /packages/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-chart-demo", 3 | "version": "0.3.4", 4 | "private": true, 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "start": "webpack-dev-server --progress", 9 | "prebuild": "rimraf dist", 10 | "build:app": "webpack", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "MIT", 16 | "dependencies": { 17 | "aurelia-chart": "^0.3.5" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/aurelia-chart/src/index.ts: -------------------------------------------------------------------------------- 1 | import { ModelObserver } from './observers/model-observer'; 2 | import { FrameworkConfiguration, PLATFORM } from 'aurelia-framework'; 3 | 4 | export function configure(aurelia: FrameworkConfiguration) { 5 | aurelia.globalResources([ 6 | PLATFORM.moduleName('./elements/chart-element'), 7 | PLATFORM.moduleName('./attributes/chart-attribute') 8 | ]); 9 | aurelia.container.registerTransient(ModelObserver); 10 | } 11 | 12 | export { ChartElement } from './elements/chart-element'; 13 | -------------------------------------------------------------------------------- /packages/demo/src/main.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-unassigned-import 2 | import 'aurelia-bootstrapper'; 3 | import { Aurelia, PLATFORM } from 'aurelia-framework'; 4 | import { 5 | Chart, LineController, LineElement, PointElement, LinearScale, Title, DoughnutController, PieController, CategoryScale, ArcElement, 6 | Legend 7 | } from 'chart.js'; 8 | 9 | Chart.register(LineController, LineElement, PointElement, LinearScale, Title, DoughnutController, PieController, CategoryScale, ArcElement, Legend); 10 | 11 | export async function configure(aurelia: Aurelia): Promise { 12 | aurelia.use 13 | .standardConfiguration() 14 | .developmentLogging() 15 | .plugin(PLATFORM.moduleName('aurelia-chart')); 16 | 17 | await aurelia.start(); 18 | await aurelia.setRoot(PLATFORM.moduleName('app')); 19 | } 20 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "amd", 4 | "moduleResolution": "node", 5 | "esModuleInterop": true, 6 | "target": "es5", 7 | "lib": [ 8 | "es2017", 9 | "dom" 10 | ], 11 | "noImplicitAny": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "strictNullChecks": true, 16 | "declaration": false, 17 | "forceConsistentCasingInFileNames": true, 18 | "emitDecoratorMetadata": true, 19 | "experimentalDecorators": true, 20 | "noEmitHelpers": true, 21 | "importHelpers": true, 22 | "skipLibCheck": true, 23 | "sourceMap": true, 24 | "newLine": "lf", 25 | "downlevelIteration": true 26 | }, 27 | "exclude": [ 28 | ".vscode", 29 | "dist", 30 | "doc", 31 | "node_modules", 32 | "test", 33 | "karma.conf.ts" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /doc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.3.4](https://github.com/grofit/aurelia-chart/compare/0.3.0...0.3.4) (2023-05-18) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * **chart:** add property change handler back ([ca03b60](https://github.com/grofit/aurelia-chart/commit/ca03b6050909a67a7185db11671f4104c800aaa9)) 7 | * **chart-element:** do not clone data ([55652f8](https://github.com/grofit/aurelia-chart/commit/55652f85e7d58f3c191a3497573d7fb93f4cf65b)) 8 | * **chart-element:** use PLATFORM.moduleName ([4028238](https://github.com/grofit/aurelia-chart/commit/4028238adb8d2f653d048ba71d540b0cefe4bcc6)) 9 | 10 | 11 | 12 | ## 0.2.0 (2015-06-08) 13 | 14 | 15 | #### Bug Fixes 16 | 17 | * **all:** 18 | * update to latest plugin api ([a050d736](http://github.com/aurelia/skeleton-plugin/commit/a050d736d32811066ffa902615cc73e1a5cbb6e3)) 19 | * update compiler ([faf51acc](http://github.com/aurelia/skeleton-plugin/commit/faf51accc1514c6767eaed60df16dd3d586b5cc5)) 20 | 21 | 22 | #### Features 23 | 24 | * **all:** initial commit of skeleton ([51a036d1](http://github.com/aurelia/skeleton-plugin/commit/51a036d146750a0bafd443dbc3def51ef7f89f6e)) 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Lee Prosser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/aurelia-chart/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Lee Prosser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/demo/src/app.html: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-chart-monorepo", 3 | "private": true, 4 | "version": "0.3.5", 5 | "workspaces": [ 6 | "packages/aurelia-chart", 7 | "packages/demo" 8 | ], 9 | "scripts": { 10 | "lint": "eslint -c .eslintrc.js packages/**/src/*.ts", 11 | "build": "cd packages/aurelia-chart && npm run build", 12 | "start": "cd packages/demo && npm start", 13 | "changelog": "cross-env conventional-changelog -p angular -i doc/CHANGELOG.md -s", 14 | "deploy": "cd packages/demo && npm run build:demo && cd ../.. && deploy.sh", 15 | "publish:latest": "cd packages/aurelia-chart && npm publish" 16 | }, 17 | "devDependencies": { 18 | "@typescript-eslint/eslint-plugin": "^5.59.6", 19 | "@typescript-eslint/parser": "^5.59.6", 20 | "aurelia-bootstrapper": "^2.4.0", 21 | "aurelia-event-aggregator": "^1.0.3", 22 | "aurelia-framework": "^1.4.1", 23 | "aurelia-history-browser": "^1.4.0", 24 | "aurelia-logging-console": "^1.1.1", 25 | "aurelia-templating-binding": "^1.6.0", 26 | "aurelia-templating-resources": "^1.14.3", 27 | "aurelia-templating-router": "^1.5.0", 28 | "aurelia-webpack-plugin": "^5.0.5", 29 | "chart.js": "^4.3.0", 30 | "concurrently": "^8.0.1", 31 | "conventional-changelog-cli": "^2.2.2", 32 | "copyfiles": "^2.4.1", 33 | "cross-env": "^7.0.3", 34 | "eslint": "^8.40.0", 35 | "eslint-plugin-compat": "^4.1.4", 36 | "eslint-plugin-import": "^2.27.5", 37 | "html-loader": "^4.2.0", 38 | "html-webpack-plugin": "^5.5.1", 39 | "rimraf": "^5.0.1", 40 | "ts-loader": "^9.4.2", 41 | "tslib": "^2.5.1", 42 | "typescript": "^5.0.4", 43 | "webpack": "^5.83.1", 44 | "webpack-bundle-analyzer": "^4.8.0", 45 | "webpack-cli": "^5.1.1", 46 | "webpack-dev-server": "^4.15.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/aurelia-chart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-chart", 3 | "version": "0.3.5", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "description": "A simple element to handle showing charts (uses chart js behind the scenes)", 8 | "keywords": [ 9 | "aurelia", 10 | "elements", 11 | "attributes", 12 | "charts" 13 | ], 14 | "homepage": "http://aurelia.io", 15 | "bugs": { 16 | "url": "https://github.com/grofit/aurelia-chart/issues" 17 | }, 18 | "license": "MIT", 19 | "author": "https://github.com/grofit", 20 | "contributors": [], 21 | "main": "dist/commonjs/index.js", 22 | "module": "dist/native-modules/index.js", 23 | "typings": "dist/types/index.d.ts", 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/grofit/aurelia-chart" 27 | }, 28 | "files": [ 29 | "dist" 30 | ], 31 | "scripts": { 32 | "build-ts:amd": "tsc -p tsconfig.build.json -t es5 -m amd --outDir dist/amd", 33 | "build-ts:cjs": "tsc -p tsconfig.build.json -t es5 -m commonjs --outDir dist/commonjs", 34 | "build-ts:ntv": "tsc -p tsconfig.build.json -t es5 -m es6 --outDir dist/native-modules", 35 | "build-ts:es6": "tsc -p tsconfig.build.json -t es6 -m es6 --outDir dist/es2015", 36 | "build-ts:types": "tsc -p tsconfig.build.json --skipLibCheck -d --emitDeclarationOnly --declarationDir dist/types", 37 | "build-assets:amd": "copyfiles -u 1 src/**/*.html src/**/*.css dist/amd", 38 | "build-assets:cjs": "copyfiles -u 1 src/**/*.html src/**/*.css dist/commonjs", 39 | "build-assets:ntv": "copyfiles -u 1 src/**/*.html src/**/*.css dist/native-modules", 40 | "build-assets:es6": "copyfiles -u 1 src/**/*.html src/**/*.css dist/es2015", 41 | "prebuild": "rimraf dist", 42 | "build": "concurrently \"npm:build-ts:*\" && concurrently \"npm:build-assets:*\"" 43 | }, 44 | "peerDependencies": { 45 | "aurelia-framework": "^1.4.1", 46 | "chart.js": "^4.3.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/demo/src/app.ts: -------------------------------------------------------------------------------- 1 | import { ChartData } from 'chart.js'; 2 | 3 | export class App { 4 | constructor() { 5 | this.resetPieData(); 6 | this.resetLineData(); 7 | } 8 | 9 | DynamicDoughnutData: ChartData; 10 | SimpleLineData: ChartData; 11 | 12 | resetPieData() { 13 | this.DynamicDoughnutData = { 14 | labels: ['Red', 'Green', 'Yellow'], 15 | datasets: [ 16 | { 17 | data: [300, 50, 100], 18 | backgroundColor: [ 19 | '#FF6384', 20 | '#36A2EB', 21 | '#FFCE56' 22 | ], 23 | hoverBackgroundColor: [ 24 | '#FF6384', 25 | '#36A2EB', 26 | '#FFCE56' 27 | ] 28 | }] 29 | }; 30 | } 31 | 32 | resetLineData() { 33 | this.SimpleLineData = { 34 | labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], 35 | datasets: [ 36 | { 37 | label: 'Healthy People', 38 | backgroundColor: 'rgba(220,220,220,0.2)', 39 | borderColor: 'rgba(220,220,220,1)', 40 | pointBackgroundColor: 'rgba(220,220,220,1)', 41 | pointBorderColor: '#fff', 42 | pointHoverBackgroundColor: '#fff', 43 | pointHoverBorderColor: 'rgba(220,220,220,1)', 44 | data: [65, 59, 80, 81, 56, 55, 40], 45 | cubicInterpolationMode: 'default', 46 | tension: 0.4 47 | }, 48 | { 49 | label: 'Ill People', 50 | backgroundColor: 'rgba(151,187,205,0.2)', 51 | borderColor: 'rgba(151,187,205,1)', 52 | pointBackgroundColor: 'rgba(151,187,205,1)', 53 | pointBorderColor: '#fff', 54 | pointHoverBackgroundColor: '#fff', 55 | pointHoverBorderColor: 'rgba(151,187,205,1)', 56 | data: [28, 48, 40, 19, 86, 27, 90], 57 | cubicInterpolationMode: 'default', 58 | tension: 0.4 59 | } 60 | ] 61 | }; 62 | } 63 | 64 | addEntry() { 65 | this.DynamicDoughnutData.labels?.push('New Colour'); 66 | this.DynamicDoughnutData.datasets![0].data?.push(50); 67 | (this.DynamicDoughnutData.datasets![0].backgroundColor as string[]).push('#B4FD5C'); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /packages/demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const path = require('path'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const AureliaWebpackPlugin = require('aurelia-webpack-plugin'); 5 | 6 | const outDir = path.resolve(__dirname, 'dist'); 7 | module.exports = function ({ production = '', stats = 'errors-only' } = {}) { 8 | const cssLoaders = [{ loader: 'css-loader', options: { esModule: false } }, 'postcss-loader']; 9 | 10 | return { 11 | mode: production === 'production' ? 'production' : 'development', 12 | devtool: production ? false : 'source-map', 13 | output: { 14 | path: outDir, 15 | filename: '[name].[fullhash].js', 16 | chunkFilename: '[name].[chunkhash].js', 17 | pathinfo: false 18 | }, 19 | stats: stats, 20 | resolve: { 21 | extensions: ['.ts', '.js'], 22 | modules: ['src', 'node_modules', '../../node_modules'].map(x => path.resolve(x)), 23 | alias: { 24 | 'src': path.resolve(__dirname, 'src'), 25 | 'aurelia-chart': path.resolve(__dirname, `../aurelia-chart/src`) 26 | } 27 | }, 28 | entry: { 29 | app: './src/main.ts' 30 | }, 31 | module: { 32 | rules: [ 33 | { test: /\.(woff|woff2|png|eot|ttf|svg)(\?|$)/, type: 'asset' }, 34 | { test: /\.ts$/, loader: 'ts-loader' }, 35 | { test: /\.html$/, loader: 'html-loader' }, 36 | // { test: /\.scss$/i, issuer: /(\.html|empty-entry\.js)$/i, use: scssLoaders }, 37 | // { test: /\.scss$/i, issuer: /\.ts$/i, use: ['style-loader', ...scssLoaders] }, 38 | { test: /\.css$/i, issuer: [{ not: /\.html$/i }], use: ['style-loader', 'css-loader'] }, 39 | { 40 | test: /\.css$/i, issuer: /\.html$/i, 41 | // CSS required in templates cannot be extracted safely 42 | // because Aurelia would try to require it again in runtime 43 | use: ['css-loader'] 44 | }, 45 | ] 46 | }, 47 | plugins: [ 48 | new AureliaWebpackPlugin.AureliaPlugin({ 49 | aureliaApp: 'src/main', 50 | dist: 'es2015', 51 | viewsFor: '{**/!(tslib)*.{ts,js},../**/*.{ts,js}}' 52 | }), 53 | new AureliaWebpackPlugin.GlobDependenciesPlugin({ 'main': ['src/{views,elements,converters,attributes}/**/*.{ts,html}'] }), 54 | new HtmlWebpackPlugin({ template: './index.ejs' }) 55 | ] 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /packages/aurelia-chart/src/attributes/chart-attribute.ts: -------------------------------------------------------------------------------- 1 | import { inject, customAttribute, bindable, bindingMode } from 'aurelia-framework'; 2 | import { ModelObserver } from '../observers/model-observer'; 3 | import { Chart, ChartOptions, ChartData, ChartConfiguration, ChartType } from 'chart.js'; 4 | 5 | @customAttribute('chart') 6 | @inject(Element, ModelObserver) 7 | export class ChartAttribute { 8 | constructor(private element: HTMLCanvasElement, private modelObserver: ModelObserver) { } 9 | 10 | activeChart?: Chart; 11 | private chartData: ChartConfiguration; 12 | 13 | @bindable 14 | type: ChartType; 15 | typeChanged() { 16 | this.chartData.type = this.type; 17 | if (this.isObserving) { 18 | this.refreshChart(); 19 | this.modelObserver.unsubscribe(); 20 | this.subscribeToChanges(); 21 | } 22 | } 23 | 24 | @bindable 25 | data: ChartData; 26 | dataChanged() { 27 | this.chartData.data = this.data; 28 | if (this.isObserving) { 29 | this.refreshChart(); 30 | this.modelObserver.unsubscribe(); 31 | this.subscribeToChanges(); 32 | } 33 | } 34 | 35 | @bindable 36 | shouldUpdate: boolean | string; 37 | 38 | private get isObserving() { 39 | return this.shouldUpdate === true || this.shouldUpdate === 'true'; 40 | } 41 | 42 | @bindable 43 | throttle?: number; 44 | 45 | @bindable({ defaultBindingMode: bindingMode.twoWay }) 46 | nativeOptions: ChartOptions = {}; 47 | 48 | bind() { 49 | // prevent initial changed handlers call 50 | } 51 | 52 | attached() { 53 | this.chartData = { 54 | type: this.type, 55 | data: this.data, 56 | options: this.nativeOptions 57 | }; 58 | 59 | this.activeChart = new Chart(this.element, this.chartData); 60 | this.nativeOptions = this.activeChart.options; 61 | this.refreshChart(); 62 | 63 | if (this.isObserving) { 64 | this.subscribeToChanges(); 65 | } 66 | } 67 | 68 | detached() { 69 | if (this.isObserving) { 70 | this.modelObserver.unsubscribe(); 71 | } 72 | 73 | this.activeChart?.destroy(); 74 | this.activeChart = undefined; 75 | } 76 | 77 | refreshChart = () => { 78 | if (this.activeChart) { 79 | this.activeChart.update(); 80 | this.activeChart.resize(); 81 | } 82 | }; 83 | 84 | subscribeToChanges() { 85 | this.modelObserver.throttle = this.throttle ?? 100; 86 | this.modelObserver.observe(this.data, this.refreshChart); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /packages/aurelia-chart/src/elements/chart-element.ts: -------------------------------------------------------------------------------- 1 | import { inject, customElement, useView, bindable, bindingMode, PLATFORM } from 'aurelia-framework'; 2 | import { ModelObserver } from '../observers/model-observer'; 3 | import { Chart, ChartConfiguration, ChartData, ChartOptions, ChartType } from 'chart.js'; 4 | 5 | @customElement('chart') 6 | @inject(ModelObserver) 7 | @useView(PLATFORM.moduleName('./chart-element.html')) 8 | export class ChartElement { 9 | constructor(private modelObserver: ModelObserver) { } 10 | 11 | activeChart?: Chart; 12 | private chartData: ChartConfiguration; 13 | 14 | @bindable 15 | type: ChartType; 16 | typeChanged() { 17 | this.chartData.type = this.type; 18 | if (this.isObserving) { 19 | this.refreshChart(); 20 | this.modelObserver.unsubscribe(); 21 | this.subscribeToChanges(); 22 | } 23 | } 24 | 25 | @bindable 26 | data: ChartData; 27 | dataChanged() { 28 | this.chartData.data = this.data; 29 | if (this.isObserving) { 30 | this.refreshChart(); 31 | this.modelObserver.unsubscribe(); 32 | this.subscribeToChanges(); 33 | } 34 | } 35 | 36 | @bindable 37 | shouldUpdate: boolean | string; 38 | 39 | private get isObserving() { 40 | return this.shouldUpdate === true || this.shouldUpdate === 'true'; 41 | } 42 | 43 | @bindable 44 | throttle?: number; 45 | 46 | @bindable({ defaultBindingMode: bindingMode.twoWay }) 47 | nativeOptions: ChartOptions = {}; 48 | 49 | @bindable 50 | canvasElement: HTMLCanvasElement; 51 | 52 | bind() { 53 | // prevent initial changed handlers call 54 | } 55 | 56 | attached() { 57 | this.chartData = { 58 | type: this.type, 59 | data: this.data, 60 | options: this.nativeOptions 61 | }; 62 | 63 | this.activeChart = new Chart(this.canvasElement, this.chartData); 64 | this.nativeOptions = this.activeChart.options; 65 | this.refreshChart(); 66 | 67 | if (this.isObserving) { 68 | this.subscribeToChanges(); 69 | } 70 | } 71 | 72 | detached() { 73 | if (this.isObserving) { 74 | this.modelObserver.unsubscribe(); 75 | } 76 | 77 | this.activeChart?.destroy(); 78 | this.activeChart = undefined; 79 | } 80 | 81 | refreshChart = () => { 82 | if (this.activeChart) { 83 | this.activeChart.update(); 84 | this.activeChart.resize(); 85 | } 86 | }; 87 | 88 | subscribeToChanges() { 89 | this.modelObserver.throttle = this.throttle ?? 100; 90 | this.modelObserver.observe(this.data.datasets, this.refreshChart); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /packages/aurelia-chart/src/observers/model-observer.ts: -------------------------------------------------------------------------------- 1 | import { BindingEngine, inject, Disposable, CollectionObserver } from 'aurelia-framework'; 2 | 3 | @inject(BindingEngine) 4 | export class ModelObserver { 5 | throttle = 100; 6 | 7 | private throttleTimeout?: ReturnType; 8 | private activeSubscriptions: Disposable[] = []; 9 | 10 | constructor(private bindingEngine: BindingEngine) { } 11 | 12 | observe = (model: unknown, onChange: () => void) => { 13 | const subscriptions: CollectionObserver['subscribe'][] = []; 14 | this.getAllSubscriptions(model, subscriptions); 15 | 16 | const throttledHandler = () => { 17 | if (this.throttle <= 0) { 18 | return onChange(); 19 | } 20 | 21 | if (!this.throttleTimeout) { 22 | this.throttleTimeout = setTimeout(() => { 23 | this.throttleTimeout = undefined; 24 | onChange(); 25 | }, this.throttle); 26 | } 27 | }; 28 | 29 | for (let i = 0; i < subscriptions.length; i++) { 30 | const outstandingSubscription = subscriptions[i](throttledHandler); 31 | this.activeSubscriptions.push(outstandingSubscription); 32 | } 33 | }; 34 | 35 | unsubscribe = () => { 36 | for (let i = 0; i < this.activeSubscriptions.length; i++) { 37 | this.activeSubscriptions[i].dispose(); 38 | } 39 | 40 | this.activeSubscriptions = []; 41 | }; 42 | 43 | private getObjectType(obj: unknown) { 44 | if (obj instanceof Date) { 45 | return 'date'; 46 | } else if (obj instanceof Array) { 47 | // return 'array'; 48 | } 49 | return typeof obj; 50 | } 51 | 52 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 53 | private getAllSubscriptions(model: any, subscriptions: CollectionObserver['subscribe'][]) { 54 | if (model instanceof Array) { 55 | const subscription = this.bindingEngine.collectionObserver(model).subscribe; 56 | subscriptions.push(subscription); 57 | } 58 | 59 | for (const property in model) { 60 | const typeOfData = this.getObjectType(model[property]); 61 | switch (typeOfData) { 62 | case 'object': 63 | this.getAllSubscriptions(model[property], subscriptions); 64 | break; 65 | // case 'array': { 66 | // const underlyingArray = model[property]() as unknown[]; 67 | // underlyingArray.forEach((_, index) => this._getAllSubscriptions(underlyingArray[index], subscriptions)); 68 | 69 | // const arraySubscription = this.bindingEngine.propertyObserver(model, property).subscribe; 70 | // if (arraySubscription) { 71 | // subscriptions.push(arraySubscription); 72 | // } 73 | // break; 74 | // } 75 | default: { 76 | const subscription = this.bindingEngine.propertyObserver(model, property).subscribe; 77 | if (subscription) { 78 | subscriptions.push(subscription); 79 | } 80 | break; 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Aurelia-Chart 2 | 3 | A simple binding to let aurelia and chartjs (2.x) come together for the greater good. 4 | 5 | It supports the basic graph types and should work with any custom ones. 6 | 7 | ## IMPORTANT CHANGES 8 | 9 | The latest version 0.3.0 uses ChartJs 3.x version so syntax needs to match that. 10 | 11 | Since version 0.2.0 of this library it has moved over to use the newer chartjs 2.x, which means schemas 12 | are now slightly different for certain graphs (like pies) and some of the properties have been renamed. 13 | So if you need to stick with the old chartjs (1.x) syntax use versions of this library < 0.2.0. Also in 14 | the latest chartjs the type syntax is lower case now, so you no longer need to worry about caps. 15 | 16 | ## Install 17 | 18 | ### JSPM 19 | use JSPM: 20 | 21 | ```sh 22 | jspm install npm:aurelia-chart 23 | ``` 24 | 25 | then include the plugin in aurelia 26 | 27 | ```sh 28 | aurelia.use.plugin("aurelia-chart"); 29 | ``` 30 | 31 | ### Webpack 32 | use npm to install Aurelia-Chart 33 | 34 | ```sh 35 | npm install aurelia-chart --save 36 | ``` 37 | 38 | then modify your `package.json` to include the Aurelia-Chart resources 39 | ```javascript 40 | dependencies { 41 | ... 42 | }, 43 | "aurelia": { 44 | "build": { 45 | "resources": [ 46 | "aurelia-chart/elements/chart-element", 47 | "aurelia-chart/attributes/chart-attribute" 48 | ] 49 | } 50 | } 51 | ``` 52 | 53 | ## Example 54 | 55 | After MANY hours of soul destroying asking of questions and finding out system.js seems to have a weird bug, 56 | there is now a space age example available for you to see: 57 | 58 | [View JSPM Example](https://rawgit.com/grofit/aurelia-chart/master/examples/jspm/index.html) 59 | [View Webpack Example](https://rawgit.com/grofit/aurelia-chart/master/examples/webpack/index.html) 60 | 61 | You can see the code and everything in the examples folder! 62 | 63 | ## Quirks 64 | 65 | So there is a lot of magic behind the scenes to allow for observable hook-ins, there are a few issues 66 | which require a bit of advance warning. 67 | 68 | * It is advised you set a throttle when you use `should-update`, and a graph will only update if `should-update` is true 69 | 70 | It is a bit more resource intensive than we would like dynamically updating the data in the charts, it is not 71 | super meltdown but it can slow things down if you are changing a lot of data in a short space of time. So it is 72 | recommended to put a throttle on for at least 100 or higher to make sure you are not refreshing too much. 73 | 74 | ## Usage 75 | The element expects a type element describing what type of chart you want and the data you wish to expose: 76 | ``` 77 | 78 | ``` 79 | 80 | Or it can be called with a options if you require more control over the chart: 81 | ``` 82 | 83 | ``` 84 | 85 | Or you can tell it to listen to observable changes: 86 | ``` 87 | 88 | ``` 89 | 90 | Finally there is also support for attributes directly on the canvas: 91 | ``` 92 | 93 | ``` 94 | 95 | So you can have finer grained control over the element yourself if needed. 96 | 97 | The chartjs specific options can be found here: 98 | 99 | http://www.chartjs.org/docs/#line-chart-chart-options 100 | 101 | http://www.chartjs.org/docs/#bar-chart-chart-options 102 | 103 | http://www.chartjs.org/docs/#radar-chart-chart-options 104 | 105 | http://www.chartjs.org/docs/#polar-area-chart-chart-options 106 | 107 | http://www.chartjs.org/docs/#doughnut-pie-chart-chart-options 108 | 109 | The available attributes are: 110 | 111 | * **type** - The type of chart you want, i.e. Pie, Bar, Doughnut etc, make sure the caps matches or it will blow up 112 | * **data** - The data you want to put in, should match the desired format of data in the ChartJS documentation, observables will be translated for you 113 | * **should-update** - This option tells the binding to scan for observables in the data and refresh the chart when they change 114 | * **throttle** - This option tells the binding to throttle updates by the desired amount, defaults to 100 115 | * **native-options** - The options based upon the ChartJS options documented above, there are a couple of unique ones which we use 116 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | root: true, 4 | extends: [ 5 | 'eslint:recommended', 6 | // 'plugin:jsdoc/recommended', 7 | 'plugin:@typescript-eslint/eslint-recommended', 8 | 'plugin:@typescript-eslint/recommended', 9 | 'plugin:@typescript-eslint/recommended-requiring-type-checking', 10 | // 'plugin:sonarjs/recommended', 11 | 'plugin:import/typescript' 12 | ], 13 | parserOptions: { 14 | ecmaVersion: 2019, 15 | project: './tsconfig.json', 16 | sourceType: 'module', 17 | tsconfigRootDir: __dirname, 18 | createDefaultProgram: true 19 | }, 20 | env: { 21 | browser: true, 22 | es6: true 23 | }, 24 | globals: { 25 | MutationObserver: 'readonly', 26 | SharedArrayBuffer: 'readonly', 27 | M: false 28 | }, 29 | plugins: [ 30 | 'compat', 31 | 'import', 32 | // 'jsdoc', 33 | // 'sonarjs' 34 | ], 35 | reportUnusedDisableDirectives: true, 36 | rules: { 37 | // Opinionated overrides of the default recommended rules: 38 | '@typescript-eslint/indent': 'off', // Disabled until typescript-eslint properly fixes indentation (see https://github.com/typescript-eslint/typescript-eslint/issues/1232) - there are recurring issues and breaking changes, and this rule usually isn't violated due to autoformatting anyway. 39 | '@typescript-eslint/interface-name-prefix': 'off', 40 | '@typescript-eslint/explicit-function-return-type': 'off', 41 | '@typescript-eslint/no-empty-interface': 'off', 42 | '@typescript-eslint/no-inferrable-types': 'off', // Turn no-inferrable-types off in order to make the code consistent in its use of type decorations. 43 | '@typescript-eslint/no-non-null-assertion': 'off', 44 | '@typescript-eslint/no-use-before-define': 'off', 45 | 'security/detect-object-injection': 'off', 46 | 'sonarjs/cognitive-complexity': 'off', 47 | 'sonarjs/no-identical-functions': 'off', 48 | 'sonarjs/no-duplicate-string': 'off', 49 | 'no-dupe-class-members': 'off', 50 | 51 | // Opinionated non default rules: 52 | '@typescript-eslint/explicit-member-accessibility': 'off', 53 | '@typescript-eslint/await-thenable': 'error', 54 | '@typescript-eslint/adjacent-overload-signatures': 'error', 55 | '@typescript-eslint/array-type': 'error', 56 | '@typescript-eslint/ban-types': ['error', { 57 | 'types': { 58 | // '{}': 'Avoid using the `{}` type. Prefer a specific lookup type, like `Record`, or use `object` (lowercase) when referring simply to non-primitives.', 59 | Function: 'Avoid using the `Function` type. Prefer a specific function type, like `() => void`, or use `Constructable` / `Class` when referring to a constructor function.', 60 | Boolean: { message: 'Use boolean instead', fixWith: 'boolean' }, 61 | Number: { message: 'Use number instead', fixWith: 'number' }, 62 | String: { message: 'Use string instead', fixWith: 'string' }, 63 | Object: { message: 'Use Record instead', fixWith: 'Record' }, 64 | Symbol: { message: 'Use symbol instead', fixWith: 'symbol' } 65 | } 66 | }], 67 | '@typescript-eslint/brace-style': ['error', '1tbs', { allowSingleLine: true }], 68 | '@typescript-eslint/consistent-type-assertions': ['error', { assertionStyle: 'as', objectLiteralTypeAssertions: 'never' }], 69 | '@typescript-eslint/func-call-spacing': ['error', 'never'], 70 | '@typescript-eslint/member-delimiter-style': 'error', 71 | '@typescript-eslint/member-ordering': ['error', { default: ['signature', 'field'] }], 72 | '@typescript-eslint/no-dynamic-delete': 'error', 73 | '@typescript-eslint/no-empty-function': ['error', { 'allow': ['protected-constructors', 'private-constructors'] }], 74 | '@typescript-eslint/no-extra-non-null-assertion': 'error', 75 | '@typescript-eslint/no-extraneous-class': 'off', 76 | '@typescript-eslint/no-floating-promises': 'off', 77 | '@typescript-eslint/no-for-in-array': 'error', 78 | '@typescript-eslint/no-misused-new': 'error', 79 | '@typescript-eslint/no-misused-promises': 'off', 80 | '@typescript-eslint/no-namespace': 'error', 81 | '@typescript-eslint/no-parameter-properties': 'off', 82 | '@typescript-eslint/no-require-imports': 'error', 83 | '@typescript-eslint/no-unnecessary-qualifier': 'error', 84 | '@typescript-eslint/no-unnecessary-type-arguments': 'error', 85 | '@typescript-eslint/no-unused-expressions': 'error', 86 | '@typescript-eslint/no-useless-constructor': 'error', 87 | '@typescript-eslint/prefer-for-of': 'off', 88 | '@typescript-eslint/prefer-function-type': 'error', 89 | '@typescript-eslint/prefer-includes': 'error', 90 | '@typescript-eslint/prefer-readonly': 'off', 91 | '@typescript-eslint/prefer-regexp-exec': 'error', 92 | '@typescript-eslint/prefer-string-starts-ends-with': 'error', 93 | '@typescript-eslint/require-await': 'error', 94 | '@typescript-eslint/return-await': 'error', 95 | '@typescript-eslint/semi': 'error', 96 | '@typescript-eslint/space-before-function-paren': ['error', { 97 | anonymous: 'always', 98 | named: 'never', 99 | asyncArrow: 'always' 100 | }], 101 | '@typescript-eslint/triple-slash-reference': ['error', { path: 'never', types: 'always', lib: 'never' }], 102 | '@typescript-eslint/type-annotation-spacing': 'error', 103 | '@typescript-eslint/explicit-module-boundary-types': 'off', 104 | '@typescript-eslint/no-unsafe-assignment': 'off', 105 | '@typescript-eslint/no-unsafe-member-access': 'off', 106 | '@typescript-eslint/no-unsafe-call': 'off', 107 | 'compat/compat': 'off', 108 | 'import/default': 'error', 109 | 'import/export': 'error', 110 | 'import/extensions': ['error', 'never', { css: 'always', html: 'always', scss: 'always' }], 111 | 'import/no-absolute-path': 'error', 112 | 'import/no-duplicates': 'error', 113 | 'import/no-extraneous-dependencies': ['off', { 114 | devDependencies: [ 115 | 'examples/**', 116 | 'scripts/**', 117 | 'test/**', 118 | 'gulpfile.js' 119 | ], 120 | optionalDependencies: false, 121 | peerDependencies: false 122 | }], 123 | 'import/no-mutable-exports': 'error', 124 | 'import/no-nodejs-modules': 'error', 125 | 'import/no-self-import': 'error', 126 | 'import/no-unassigned-import': 'error', 127 | 'import/no-useless-path-segments': ['error'], 128 | 'import/order': ['error', { 'groups': [], 'newlines-between': 'ignore' }], 129 | 'import/no-deprecated': 'off', // this rule is extremely slow (takes 95% of the time of the full lint operation) so we disable it for that reason only 130 | // 'jsdoc/check-alignment': 'error', 131 | // 'jsdoc/check-indentation': 'error', 132 | // 'jsdoc/check-tag-names': ['error', { 133 | // definedTags: [ 134 | // 'chainable', 135 | // 'internal' 136 | // ] 137 | // }], 138 | // 'jsdoc/check-syntax': 'error', 139 | // 'jsdoc/newline-after-description': 'error', 140 | // 'jsdoc/require-hyphen-before-param-description': ['error', 'always'], 141 | // 'sonarjs/no-small-switch': 'off', 142 | // 'sonarjs/no-useless-catch': 'error', 143 | // 'sonarjs/prefer-immediate-return': 'error', 144 | 'array-callback-return': 'error', 145 | 'eol-last': ['error', 'always'], 146 | 'func-call-spacing': 'off', // See @typescript-eslint/func-call-spacing 147 | 'function-call-argument-newline': ['error', 'consistent'], 148 | 'grouped-accessor-pairs': ['error', 'getBeforeSet'], 149 | 'max-lines-per-function': ['error', 200], 150 | 'new-parens': ['error', 'always'], 151 | 'no-caller': 'error', 152 | 'no-case-declarations': 'error', 153 | 'no-constant-condition': 'error', 154 | 'no-dupe-else-if': 'error', 155 | 'no-eval': 'error', 156 | 'no-extra-bind': 'error', 157 | 'no-extra-semi': 'error', 158 | 'no-import-assign': 'error', 159 | 'no-multiple-empty-lines': ['error', { max: 1 }], 160 | 'no-new-func': 'error', 161 | 'no-new-wrappers': 'error', 162 | 'no-octal-escape': 'error', 163 | 'no-prototype-builtins': 'error', 164 | 'no-restricted-properties': ['error', 165 | { property: 'substr', message: '"substr" is considered a legacy function and should be avoided when possible. Use "substring" instead.' } 166 | ], 167 | 'no-restricted-syntax': ['error', 168 | { selector: 'MemberExpression[object.name=\'document\'][property.name=\'cookies\']', message: 'Usage of document.cookies is forbidden.' }, 169 | { selector: 'MemberExpression[object.name=\'document\'][property.name=\'domain\']', message: 'Usage of document.domain is forbidden.' }, 170 | { selector: 'MemberExpression[object.name=\'document\'][property.name=\'write\']', message: 'Usage of document.write is forbidden.' }, 171 | { selector: 'CallExpression[callee.name=\'execScript\']', message: 'Usage of execScript is forbidden.' } 172 | ], 173 | 'no-return-await': 'error', 174 | 'no-sequences': 'error', 175 | 'no-setter-return': 'error', 176 | 'no-template-curly-in-string': 'error', 177 | 'no-throw-literal': 'error', 178 | 'no-undef-init': 'error', 179 | 'no-unused-expressions': 'off', // See @typescript-eslint/no-unused-expressions 180 | 'no-useless-catch': 'error', 181 | 'no-useless-escape': 'error', 182 | 'no-trailing-spaces': 'error', 183 | 'no-var': 'error', 184 | 'prefer-const': 'error', 185 | 'prefer-exponentiation-operator': 'error', 186 | 'prefer-object-spread': 'error', 187 | 'prefer-regex-literals': 'error', 188 | 'prefer-rest-params': 'error', 189 | 'prefer-spread': 'error', 190 | 'prefer-template': 'error', 191 | 'quote-props': ['error', 'consistent'], 192 | 'quotes': ['off'], 193 | 'radix': 'off', 194 | 'sort-keys': ['off'], 195 | 'space-before-function-paren': 'off', // See @typescript-eslint/space-before-function-paren 196 | 'space-in-parens': 'error', 197 | 'spaced-comment': ['error', 'always', { 198 | line: { markers: ['/'], exceptions: ['-', '+'] }, 199 | block: { markers: ['!'], exceptions: ['*'], balanced: true } 200 | }], 201 | 202 | // Things we maybe need to fix some day, so are marked as warnings for now: 203 | '@typescript-eslint/no-explicit-any': 'warn', 204 | '@typescript-eslint/no-this-alias': 'warn', 205 | '@typescript-eslint/no-unnecessary-condition': 'off', // Only false positives seen so far 206 | '@typescript-eslint/no-unnecessary-type-assertion': 'warn', 207 | '@typescript-eslint/no-unused-vars': 'warn', 208 | '@typescript-eslint/no-unused-vars-experimental': 'off', // Off for now, crashes eslint 209 | '@typescript-eslint/prefer-nullish-coalescing': ['warn', { 'forceSuggestionFixer': true }], 210 | '@typescript-eslint/prefer-optional-chain': 'warn', 211 | '@typescript-eslint/promise-function-async': 'warn', 212 | // '@typescript-eslint/quotes': ['warn', 'backtick', { avoidEscape: true }], 213 | '@typescript-eslint/require-array-sort-compare': 'warn', 214 | '@typescript-eslint/restrict-plus-operands': ['warn', { 'checkCompoundAssignments': true }], 215 | '@typescript-eslint/restrict-template-expressions': ['off', { 'allowNumber': true, 'allowBoolean': true, 'allowNullable': true }], 216 | '@typescript-eslint/strict-boolean-expressions': 'off', 217 | '@typescript-eslint/typedef': ['off', { arrowParameter: false, parameter: false, variableDeclaration: false }], 218 | '@typescript-eslint/unbound-method': 'off', // Only false positives seen so far 219 | // 'jsdoc/check-examples': 'off', 220 | // 'jsdoc/check-param-names': 'off', 221 | // 'jsdoc/match-description': 'off', 222 | // 'jsdoc/no-types': 'off', 223 | // 'jsdoc/require-description': 'off', 224 | // 'jsdoc/require-example': 'off', 225 | // 'jsdoc/require-jsdoc': 'off', 226 | // 'jsdoc/require-param': 'off', 227 | // 'jsdoc/require-param-type': 'off', 228 | // 'jsdoc/require-returns': 'off', 229 | // 'jsdoc/require-returns-type': 'off', 230 | // 'sonarjs/no-all-duplicated-branches': 'warn', 231 | // 'sonarjs/no-duplicated-branches': 'warn', 232 | // 'sonarjs/no-extra-arguments': 'warn', 233 | // 'sonarjs/no-inverted-boolean-check': 'warn', 234 | 'default-param-last': ['warn'], 235 | 'eqeqeq': 'warn', 236 | 'no-await-in-loop': 'warn', 237 | 'no-cond-assign': 'warn', 238 | 'no-console': 'warn', 239 | 'no-constructor-return': 'warn', 240 | 'no-extra-boolean-cast': 'warn', 241 | 'no-fallthrough': 'warn', 242 | 'no-inner-declarations': 'warn', 243 | 'no-shadow': 'warn', 244 | 'no-useless-computed-key': ['warn', { 'enforceForClassMembers': true }], 245 | 'no-undef': 'warn', 246 | 'require-atomic-updates': 'warn', 247 | 248 | // Off for now as they create way to much noise 249 | '@typescript-eslint/quotes': ['error', 'single'] 250 | }, 251 | overrides: [{ // Specific overrides for JS files as some TS rules don't make sense there. 252 | files: ['**/*.js'], 253 | rules: { 254 | '@typescript-eslint/explicit-member-accessibility': 'off', 255 | '@typescript-eslint/no-require-imports': 'off', 256 | '@typescript-eslint/no-var-requires': 'off', 257 | '@typescript-eslint/restrict-plus-operands': 'off', 258 | '@typescript-eslint/typedef': 'off', 259 | 'compat/compat': 'off' 260 | } 261 | }, { // Specific overrides for TS files within examples, scripts and tests as some rules don't make sense there. 262 | files: ['examples/**', 'scripts/**', 'test/**'], 263 | rules: { 264 | '@typescript-eslint/no-require-imports': 'off', 265 | '@typescript-eslint/no-var-requires': 'off', 266 | 'compat/compat': 'off', 267 | 'import/no-nodejs-modules': 'off' 268 | } 269 | }], 270 | settings: { 271 | polyfills: [ 272 | 'fetch', 273 | 'Reflect', 274 | 'Promise', 275 | 'Map', 276 | 'Set', 277 | 'Object.assign', 278 | 'WeakMap', 279 | 'WeakSet' 280 | ] 281 | } 282 | }; 283 | --------------------------------------------------------------------------------