├── .commitlintrc.json ├── .czrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ └── feature-request.yml ├── renovate.json └── workflows │ ├── checks.yml │ ├── ci.yml │ ├── commit.yml │ └── release.yml ├── .gitignore ├── .nano-staged.json ├── .npmrc ├── .prettierrc ├── .simple-git-hooks.json ├── .size-limit.cjs ├── .storybook ├── main.js ├── manager.js ├── preview.js └── theme.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets └── svelte-chartjs.png ├── package.json ├── pnpm-lock.yaml ├── sandboxes ├── bar │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── bubble │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── doughnut │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── events │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── line │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── pie │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ └── package.json ├── polar │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── radar │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── ref │ ├── App.svelte │ ├── components │ │ ├── Chart.svelte │ │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js └── scatter │ ├── App.svelte │ ├── components │ ├── Chart.svelte │ └── data.js │ ├── index.html │ ├── index.js │ ├── package.json │ └── vite.config.js ├── src ├── Bar.svelte ├── Bubble.svelte ├── Chart.svelte ├── Doughnut.svelte ├── Line.svelte ├── Pie.svelte ├── PolarArea.svelte ├── Radar.svelte ├── Scatter.svelte ├── index.ts ├── types │ ├── chart.ts │ ├── html.ts │ └── index.ts └── utils │ ├── events.ts │ ├── index.ts │ └── svelte.ts ├── stories ├── bar.stories.ts ├── bubble.stories.ts ├── chart.stories.ts ├── doughnut.stories.ts ├── line.stories.ts ├── pie.stories.ts ├── polar.stories.ts ├── radar.stories.ts └── scatter.stories.ts ├── svelte.config.js ├── test ├── .eslintrc ├── Bar.spec.ts ├── Bubble.spec.ts ├── Doughnut.spec.ts ├── Line.spec.ts ├── Pie.spec.ts ├── PolarArea.spec.ts ├── Radar.spec.ts ├── Scatter.spec.ts ├── setup.js └── tsconfig.json ├── tsconfig.json └── vite.config.js /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@commitlint/config-conventional"], 3 | "rules": { 4 | "body-max-line-length": [0] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.czrc: -------------------------------------------------------------------------------- 1 | { 2 | "path": "@commitlint/cz-commitlint" 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/* 2 | node_modules/* 3 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "plugins": ["vitest", "@typescript-eslint"], 4 | "parserOptions": { 5 | "ecmaVersion": 2019, 6 | "sourceType": "module", 7 | "extraFileExtensions": [".svelte"] 8 | }, 9 | "extends": [ 10 | "eslint:recommended", 11 | "plugin:import/recommended", 12 | "plugin:svelte/recommended", 13 | "plugin:@typescript-eslint/recommended" 14 | ], 15 | "env": { 16 | "browser": true, 17 | "node": true 18 | }, 19 | "overrides": [ 20 | { 21 | "files": ["*.svelte"], 22 | "parser": "svelte-eslint-parser", 23 | "rules": { 24 | "no-undef": "off" 25 | }, 26 | "parserOptions": { 27 | "parser": "@typescript-eslint/parser" 28 | } 29 | } 30 | ], 31 | "rules": { 32 | "arrow-parens": 0, 33 | "curly": [2, "multi-line"], 34 | "quotes": [2, "single", "avoid-escape"], 35 | "semi": [2, "always"], 36 | "strict": 0, 37 | "no-use-before-define": 0, 38 | "import/no-unresolved": 0, 39 | "no-inner-declarations": 0 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: "🐛 Bug Report" 2 | description: "If something isn't working as expected." 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: Thanks for taking the time to file a bug report! Please fill out this form as completely as possible. 9 | 10 | - type: markdown 11 | attributes: 12 | value: ⚠️ svelte-chartjs is just the wrapper around Chart.js, so if you are experiencing an issue with charts rendering, please create a related issue in [Chart.js repository](https://github.com/chartjs/Chart.js/issues). 13 | 14 | - type: checkboxes 15 | id: input1 16 | attributes: 17 | label: Would you like to work on a fix? 18 | options: 19 | - label: Check this if you would like to implement a PR, we are more than happy to help you go through the process. 20 | 21 | - type: textarea 22 | attributes: 23 | label: Current and expected behavior 24 | description: A clear and concise description of what the library is doing and what you would expect. 25 | validations: 26 | required: true 27 | 28 | - type: input 29 | attributes: 30 | label: Reproduction 31 | description: | 32 | Please provide issue reproduction. 33 | You can give a link to a repository with the reproduction or make a fork of [this sandbox](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/ref?file=/components/Chart.svelte) and reproduce the issue there. 34 | validations: 35 | required: true 36 | 37 | - type: input 38 | attributes: 39 | label: chart.js version 40 | description: Which version of `chart.js` are you using? 41 | placeholder: v0.0.0 42 | validations: 43 | required: true 44 | 45 | - type: input 46 | attributes: 47 | label: svelte-chartjs version 48 | description: Which version of `svelte-chartjs` are you using? 49 | placeholder: v0.0.0 50 | validations: 51 | required: true 52 | 53 | - type: textarea 54 | attributes: 55 | label: Possible solution 56 | description: If you have suggestions on a fix for the bug. 57 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | 2 | blank_issues_enabled: false 3 | contact_links: 4 | - name: 🤔 Have a Question? 5 | url: https://stackoverflow.com/questions/tagged/svelte-chartjs 6 | about: Feel free to ask questions on Stack Overflow. 7 | - name: 📊 Have a Problem With Chart.js? 8 | url: https://github.com/chartjs/Chart.js/issues 9 | about: svelte-chartjs is just the wrapper around Chart.js, so if you are experiencing an issue with charts rendering, please create a related issue in Chart.js repository. 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: "🚀 Feature Request" 2 | description: "I have a specific suggestion!" 3 | labels: ["enhancement"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: Thanks for taking the time to suggest a new feature! Please fill out this form as completely as possible. 8 | 9 | - type: markdown 10 | attributes: 11 | value: ⚠️ svelte-chartjs is just the wrapper around Chart.js, so if you are experiencing an issue with charts rendering, please create a related issue in [Chart.js repository](https://github.com/chartjs/Chart.js/issues). 12 | 13 | - type: checkboxes 14 | id: input1 15 | attributes: 16 | label: Would you like to work on this feature? 17 | options: 18 | - label: Check this if you would like to implement a PR, we are more than happy to help you go through the process. 19 | 20 | - type: textarea 21 | attributes: 22 | label: What problem are you trying to solve? 23 | description: | 24 | A concise description of what the problem is. 25 | placeholder: | 26 | I have an issue when [...] 27 | validations: 28 | required: true 29 | 30 | - type: textarea 31 | attributes: 32 | label: Describe the solution you'd like 33 | validations: 34 | required: true 35 | 36 | - type: textarea 37 | attributes: 38 | label: Describe alternatives you've considered 39 | 40 | - type: textarea 41 | attributes: 42 | label: Documentation, Adoption, Migration Strategy 43 | description: | 44 | If you can, explain how users will be able to use this and how it might be documented. Maybe a mock-up? 45 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | ":preserveSemverRanges" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Checks 2 | on: 3 | pull_request: 4 | branches: 5 | - master 6 | jobs: 7 | size: 8 | runs-on: ubuntu-latest 9 | name: Checking size 10 | if: "!contains(github.event.head_commit.message, '[ci skip]')" 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v4 14 | - name: Install pnpm 15 | uses: pnpm/action-setup@v2 16 | with: 17 | version: 8 18 | - name: Install Node 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: 20 22 | cache: 'pnpm' 23 | registry-url: 'https://registry.npmjs.org' 24 | - name: Install dependencies 25 | run: pnpm install 26 | - name: Check size 27 | uses: andresz1/size-limit-action@master 28 | with: 29 | github_token: ${{ secrets.GITHUB_TOKEN }} 30 | storybook: 31 | runs-on: ubuntu-latest 32 | name: storybook 33 | steps: 34 | - name: Checkout the repository 35 | uses: actions/checkout@v4 36 | - name: Install pnpm 37 | uses: pnpm/action-setup@v2 38 | with: 39 | version: 8 40 | - name: Install Node 41 | uses: actions/setup-node@v4 42 | with: 43 | node-version: 20 44 | cache: 'pnpm' 45 | registry-url: 'https://registry.npmjs.org' 46 | - name: Install dependencies 47 | run: pnpm install 48 | - name: Check storybook 49 | run: pnpm build:storybook 50 | editorconfig: 51 | runs-on: ubuntu-latest 52 | name: editorconfig 53 | steps: 54 | - name: Checkout the repository 55 | uses: actions/checkout@v4 56 | - name: Check editorconfig 57 | uses: editorconfig-checker/action-editorconfig-checker@v2 58 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | pull_request: 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | name: Running tests 9 | if: "!contains(github.event.head_commit.message, '[ci skip]')" 10 | steps: 11 | - name: Checkout the repository 12 | uses: actions/checkout@v4 13 | - name: Install pnpm 14 | uses: pnpm/action-setup@v2 15 | with: 16 | version: 8 17 | - name: Install Node 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: 20 21 | cache: 'pnpm' 22 | registry-url: 'https://registry.npmjs.org' 23 | - name: Install dependencies 24 | run: pnpm install 25 | - name: Run tests 26 | run: pnpm test 27 | -------------------------------------------------------------------------------- /.github/workflows/commit.yml: -------------------------------------------------------------------------------- 1 | name: Commit 2 | on: 3 | push: 4 | jobs: 5 | commitlint: 6 | runs-on: ubuntu-latest 7 | name: commitlint 8 | steps: 9 | - name: Checkout the repository 10 | uses: actions/checkout@v4 11 | with: 12 | fetch-depth: 0 13 | - name: Run commitlint 14 | uses: wagoid/commitlint-github-action@v5 15 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | release: 4 | types: [created] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | name: Publish package 9 | steps: 10 | - name: Checkout the repository 11 | uses: actions/checkout@v4 12 | - name: Install pnpm 13 | uses: pnpm/action-setup@v2 14 | with: 15 | version: 8 16 | - name: Install Node 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: 20 20 | cache: 'pnpm' 21 | registry-url: 'https://registry.npmjs.org' 22 | - name: Install dependencies 23 | run: pnpm install 24 | - name: Publish 25 | run: pnpm test && pnpm build && pnpm publish --no-git-checks 26 | env: 27 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /public/build/ 3 | 4 | .DS_Store 5 | lib 6 | dist 7 | .idea 8 | lib 9 | package 10 | 11 | 12 | # Created by https://www.gitignore.io/api/node,jetbrains+all 13 | # Edit at https://www.gitignore.io/?templates=node,jetbrains+all 14 | 15 | ### JetBrains+all ### 16 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 17 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 18 | 19 | # User-specific stuff 20 | .idea/**/workspace.xml 21 | .idea/**/tasks.xml 22 | .idea/**/usage.statistics.xml 23 | .idea/**/dictionaries 24 | .idea/**/shelf 25 | 26 | # Generated files 27 | .idea/**/contentModel.xml 28 | 29 | # Sensitive or high-churn files 30 | .idea/**/dataSources/ 31 | .idea/**/dataSources.ids 32 | .idea/**/dataSources.local.xml 33 | .idea/**/sqlDataSources.xml 34 | .idea/**/dynamic.xml 35 | .idea/**/uiDesigner.xml 36 | .idea/**/dbnavigator.xml 37 | 38 | # Gradle 39 | .idea/**/gradle.xml 40 | .idea/**/libraries 41 | 42 | # Gradle and Maven with auto-import 43 | # When using Gradle or Maven with auto-import, you should exclude module files, 44 | # since they will be recreated, and may cause churn. Uncomment if using 45 | # auto-import. 46 | # .idea/modules.xml 47 | # .idea/*.iml 48 | # .idea/modules 49 | # *.iml 50 | # *.ipr 51 | 52 | # CMake 53 | cmake-build-*/ 54 | 55 | # Mongo Explorer plugin 56 | .idea/**/mongoSettings.xml 57 | 58 | # File-based project format 59 | *.iws 60 | 61 | # IntelliJ 62 | out/ 63 | 64 | # mpeltonen/sbt-idea plugin 65 | .idea_modules/ 66 | 67 | # JIRA plugin 68 | atlassian-ide-plugin.xml 69 | 70 | # Cursive Clojure plugin 71 | .idea/replstate.xml 72 | 73 | # Crashlytics plugin (for Android Studio and IntelliJ) 74 | com_crashlytics_export_strings.xml 75 | crashlytics.properties 76 | crashlytics-build.properties 77 | fabric.properties 78 | 79 | # Editor-based Rest Client 80 | .idea/httpRequests 81 | 82 | # Android studio 3.1+ serialized cache file 83 | .idea/caches/build_file_checksums.ser 84 | 85 | ### JetBrains+all Patch ### 86 | # Ignores the whole .idea folder and all .iml files 87 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 88 | 89 | .idea/ 90 | 91 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 92 | 93 | *.iml 94 | modules.xml 95 | .idea/misc.xml 96 | *.ipr 97 | 98 | # Sonarlint plugin 99 | .idea/sonarlint 100 | 101 | ### Node ### 102 | # Logs 103 | logs 104 | *.log 105 | npm-debug.log* 106 | yarn-debug.log* 107 | yarn-error.log* 108 | lerna-debug.log* 109 | 110 | # Diagnostic reports (https://nodejs.org/api/report.html) 111 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 112 | 113 | # Runtime data 114 | pids 115 | *.pid 116 | *.seed 117 | *.pid.lock 118 | 119 | # Directory for instrumented libs generated by jscoverage/JSCover 120 | lib-cov 121 | 122 | # Coverage directory used by tools like istanbul 123 | coverage 124 | *.lcov 125 | 126 | # nyc test coverage 127 | .nyc_output 128 | 129 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 130 | .grunt 131 | 132 | # Bower dependency directory (https://bower.io/) 133 | bower_components 134 | 135 | # node-waf configuration 136 | .lock-wscript 137 | 138 | # Compiled binary addons (https://nodejs.org/api/addons.html) 139 | build/Release 140 | 141 | # Dependency directories 142 | node_modules/ 143 | jspm_packages/ 144 | 145 | # TypeScript v1 declaration files 146 | typings/ 147 | 148 | # TypeScript cache 149 | *.tsbuildinfo 150 | 151 | # Optional npm cache directory 152 | .npm 153 | 154 | # Optional eslint cache 155 | .eslintcache 156 | 157 | # Optional REPL history 158 | .node_repl_history 159 | 160 | # Output of 'npm pack' 161 | *.tgz 162 | 163 | # Yarn Integrity file 164 | .yarn-integrity 165 | 166 | # dotenv environment variables file 167 | .env 168 | .env.test 169 | 170 | # parcel-bundler cache (https://parceljs.org/) 171 | .cache 172 | 173 | # next.js build output 174 | .next 175 | 176 | # nuxt.js build output 177 | .nuxt 178 | 179 | # rollup.js default build output 180 | dist/ 181 | 182 | # ignore package bundling output 183 | .svelte-kit 184 | 185 | # Uncomment the public line if your project uses Gatsby 186 | # https://nextjs.org/blog/next-9-1#public-directory-support 187 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 188 | # public 189 | 190 | # Storybook build outputs 191 | .out 192 | .storybook-out 193 | storybook-static 194 | 195 | # vuepress build output 196 | .vuepress/dist 197 | 198 | # Serverless directories 199 | .serverless/ 200 | 201 | # FuseBox cache 202 | .fusebox/ 203 | 204 | # DynamoDB Local files 205 | .dynamodb/ 206 | 207 | # Temporary folders 208 | tmp/ 209 | temp/ 210 | 211 | # End of https://www.gitignore.io/api/node,jetbrains+all 212 | -------------------------------------------------------------------------------- /.nano-staged.json: -------------------------------------------------------------------------------- 1 | { 2 | "**/*.{js,mjs,ts,svelte}": ["prettier --write", "eslint"] 3 | } 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=false 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": true, 4 | "tabWidth": 2, 5 | "bracketSpacing": true, 6 | "arrowParens": "avoid", 7 | "trailingComma": "es5", 8 | "plugins": ["prettier-plugin-svelte"] 9 | } 10 | -------------------------------------------------------------------------------- /.simple-git-hooks.json: -------------------------------------------------------------------------------- 1 | { 2 | "commit-msg": "pnpm commitlint --edit \"$1\"", 3 | "pre-commit": "pnpm nano-staged", 4 | "pre-push": "pnpm test" 5 | } 6 | -------------------------------------------------------------------------------- /.size-limit.cjs: -------------------------------------------------------------------------------- 1 | function modifyWebpackConfig(config) { 2 | config.module.rules.push({ 3 | test: /\.svelte$/, 4 | use: 'svelte-loader' 5 | }); 6 | 7 | return config; 8 | } 9 | 10 | module.exports = [ 11 | { 12 | path: 'dist/index.js', 13 | limit: '840 B', 14 | import: '{ Chart }', 15 | modifyWebpackConfig 16 | }, 17 | { 18 | path: 'dist/index.js', 19 | limit: '1.25 KB', 20 | import: '{ Bar }', 21 | modifyWebpackConfig 22 | }, 23 | { 24 | path: 'dist/index.js', 25 | limit: '1.55 KB', 26 | import: '{ Bar, Bubble, Chart, Doughnut, Line, Pie, PolarArea, Radar, Scatter }', 27 | modifyWebpackConfig 28 | } 29 | ]; 30 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import preprocess from 'svelte-preprocess'; 3 | import { mergeConfig } from 'vite'; 4 | 5 | export default { 6 | stories: ['../stories/*.stories.@(js|ts)'], 7 | addons: ['@storybook/addon-essentials'], 8 | framework: { 9 | name: '@storybook/svelte-vite', 10 | options: { 11 | preprocess: preprocess(), 12 | }, 13 | }, 14 | viteFinal(config) { 15 | return mergeConfig(config, { 16 | resolve: { 17 | dedupe: ['@storybook/client-api'], 18 | alias: { 19 | 'svelte-chartjs': path.resolve(__dirname, '../src'), 20 | }, 21 | }, 22 | }); 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | 3 | import { theme } from './theme'; 4 | 5 | addons.setConfig({ 6 | theme, 7 | panelPosition: 'right', 8 | }); 9 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | import { configureActions } from '@storybook/addon-actions'; 2 | 3 | configureActions({ 4 | depth: 5, 5 | }); 6 | -------------------------------------------------------------------------------- /.storybook/theme.js: -------------------------------------------------------------------------------- 1 | import { create } from '@storybook/theming'; 2 | 3 | export const theme = create({ 4 | base: 'light', 5 | brandTitle: 'svelte-chartjs', 6 | brandUrl: 'https://github.com/SauravKanchan/svelte-chartjs', 7 | }); 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [3.1.5](https://github.com/SauravKanchan/svelte-chartjs/compare/v3.1.4...v3.1.5) (2024-02-06) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * **exports:** update types path to use the correct type def ([539e2c7](https://github.com/SauravKanchan/svelte-chartjs/commit/539e2c74f6900cd301d643e454865918c010a979)) 11 | 12 | ### [3.1.4](https://github.com/SauravKanchan/svelte-chartjs/compare/v3.1.3...v3.1.4) (2024-01-30) 13 | 14 | ### [3.1.3](https://github.com/SauravKanchan/svelte-chartjs/compare/v3.1.2...v3.1.3) (2024-01-30) 15 | 16 | 17 | ### Bug Fixes 18 | 19 | * **deps:** update dependency svelte to v4 ([c8a12cc](https://github.com/SauravKanchan/svelte-chartjs/commit/c8a12ccdf837121fc48ac6947d540a011f89561d)) 20 | * **size:** update size test to use the new build ([c850b88](https://github.com/SauravKanchan/svelte-chartjs/commit/c850b88352560376224e086a3bd3b66e0c7e09d5)) 21 | 22 | ### [3.1.2](https://github.com/SauravKanchan/svelte-chartjs/compare/v3.1.1...v3.1.2) (2023-01-18) 23 | 24 | 25 | ### Bug Fixes 26 | 27 | * upgrade chart.js with fixed types ([3bd69dc](https://github.com/SauravKanchan/svelte-chartjs/commit/3bd69dcf297325061401e679ef31b6d3eeaa30a5)) 28 | 29 | ### [3.1.1](https://github.com/SauravKanchan/svelte-chartjs/compare/v3.1.0...v3.1.1) (2023-01-18) 30 | 31 | 32 | ### Bug Fixes 33 | 34 | * files list to publish ([f7cb847](https://github.com/SauravKanchan/svelte-chartjs/commit/f7cb847e14e2789c3b5d008a76c6bf7a6aa5352e)) 35 | 36 | ## [3.1.0](https://github.com/SauravKanchan/svelte-chartjs/compare/v3.0.1...v3.1.0) (2022-11-17) 37 | 38 | 39 | ### Features 40 | 41 | * add chart.js v4 support ([#86](https://github.com/SauravKanchan/svelte-chartjs/issues/86)) ([cbc497c](https://github.com/SauravKanchan/svelte-chartjs/commit/cbc497c020b3e810acef8d0fb7a6cbe68d77e0f7)) 42 | 43 | 44 | ### Bug Fixes 45 | 46 | * **deps:** update dependency chart.js to v4 ([#84](https://github.com/SauravKanchan/svelte-chartjs/issues/84)) ([112b2fa](https://github.com/SauravKanchan/svelte-chartjs/commit/112b2faca1e383db4b14ed5c9578a1d1ec0ff538)) 47 | 48 | ### [3.0.1](https://github.com/SauravKanchan/svelte-chartjs/compare/v3.0.0...v3.0.1) (2022-09-20) 49 | 50 | 51 | ### Bug Fixes 52 | 53 | * typed components update fix ([#78](https://github.com/SauravKanchan/svelte-chartjs/issues/78)) ([2a34f4f](https://github.com/SauravKanchan/svelte-chartjs/commit/2a34f4f4a23b6b2860bb44d681e0ad7159fe9ae3)) 54 | 55 | ## [3.0.0](https://github.com/SauravKanchan/svelte-chartjs/compare/v2.1.1...v3.0.0) (2022-09-19) 56 | 57 | 58 | ### ⚠ BREAKING CHANGES 59 | 60 | * now package is module type, new exports in package.json 61 | 62 | ### build 63 | 64 | * use svelte-package ([#75](https://github.com/SauravKanchan/svelte-chartjs/issues/75)) ([1eb4efe](https://github.com/SauravKanchan/svelte-chartjs/commit/1eb4efefffb367fe0338e37c89d20f89dcdff807)) 65 | 66 | ### [2.1.1](https://github.com/SauravKanchan/svelte-chartjs/compare/v2.1.0...v2.1.1) (2022-08-29) 67 | 68 | 69 | ### Bug Fixes 70 | 71 | * chart ref prop type fix ([#70](https://github.com/SauravKanchan/svelte-chartjs/issues/70)) ([893d78c](https://github.com/SauravKanchan/svelte-chartjs/commit/893d78cae03c5ccb43dacabcf1b27bff958b1a5c)) 72 | 73 | ## [2.1.0](https://github.com/SauravKanchan/svelte-chartjs/compare/v2.0.1...v2.1.0) (2022-08-17) 74 | 75 | 76 | ### Features 77 | 78 | * events forwarding, getDatasetAtEvent getElementAtEvent getElementsAtEvent events utils ([#63](https://github.com/SauravKanchan/svelte-chartjs/issues/63)) ([e84bd77](https://github.com/SauravKanchan/svelte-chartjs/commit/e84bd7799ea4bd787cc20d2d28701dcca280f1ac)) 79 | * new prop types, expose chart instance ([#62](https://github.com/SauravKanchan/svelte-chartjs/issues/62)) ([d59111a](https://github.com/SauravKanchan/svelte-chartjs/commit/d59111a66f923678e85ac79d179285d89270c223)) 80 | * update mode prop ([#65](https://github.com/SauravKanchan/svelte-chartjs/issues/65)) ([d6e5506](https://github.com/SauravKanchan/svelte-chartjs/commit/d6e55060cc69b712bffb514205c0f0115dcd204d)) 81 | 82 | 83 | ### Bug Fixes 84 | 85 | * rename components Base -> Chart, Polar -> PolarArea ([#64](https://github.com/SauravKanchan/svelte-chartjs/issues/64)) ([ec905cc](https://github.com/SauravKanchan/svelte-chartjs/commit/ec905ccfaf51c0374211096e4656d061ab85f6da)) 86 | 87 | ### [2.0.1](https://github.com/SauravKanchan/svelte-chartjs/compare/v2.0.0...v2.0.1) (2022-07-20) 88 | 89 | 90 | ### Bug Fixes 91 | 92 | * add path to types ([#56](https://github.com/SauravKanchan/svelte-chartjs/issues/56)) ([a249af6](https://github.com/SauravKanchan/svelte-chartjs/commit/a249af66a58fb5c036430ec75016c7416f1ad6d2)) 93 | 94 | ## 2.0.0 (2022-07-20) 95 | 96 | 97 | ### ⚠ BREAKING CHANGES 98 | 99 | * svelte files were removed from the package, now you should use named exports 100 | * add typescript and tree-shaking for chart.js imports 101 | 102 | ### Features 103 | 104 | * add typescript ([#41](https://github.com/SauravKanchan/svelte-chartjs/issues/41)) ([2fe9aba](https://github.com/SauravKanchan/svelte-chartjs/commit/2fe9aba8d38372faee710e68746c5de20b27ba6e)) 105 | 106 | 107 | ### Bug Fixes 108 | 109 | * **base:** Add chart.destroy() to fix memory leak. Fixes [#25](https://github.com/SauravKanchan/svelte-chartjs/issues/25) ([d49ffa1](https://github.com/SauravKanchan/svelte-chartjs/commit/d49ffa1c015282bb0551e26a94341491a986981c)) 110 | 111 | 112 | * remove svelte files from package ([#54](https://github.com/SauravKanchan/svelte-chartjs/issues/54)) ([82b871b](https://github.com/SauravKanchan/svelte-chartjs/commit/82b871b1b54baa89a28c3e60256f85ed5aff7fed)) 113 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Saurav Kanchan 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-chartjs 2 | 3 | svelte-chartjs logo 4 | 5 | Svelte wrapper for [chart.js](https://www.chartjs.org/) Open for PRs and contributions! 6 | 7 | [![npm version](https://badge.fury.io/js/svelte-chartjs.svg)](https://badge.fury.io/js/svelte-chartjs) 8 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FSauravKanchan%2Fsvelte-chartjs.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FSauravKanchan%2Fsvelte-chartjs?ref=badge_shield) 9 | ![npm](https://img.shields.io/npm/dm/svelte-chartjs) 10 | 11 |
12 | Install 13 |   •   14 | Usage 15 |   •   16 | Migration guide 17 |   •   18 | Examples 19 |   •   20 | Slack 21 |   •   22 | Stack Overflow 23 |
24 |
25 | 26 | ## Install 27 | 28 | Install this library with peer dependencies: 29 | 30 | ```bash 31 | pnpm add svelte-chartjs chart.js 32 | # or 33 | yarn add svelte-chartjs chart.js 34 | # or 35 | npm i svelte-chartjs chart.js 36 | ``` 37 | 38 |
39 | 40 | Need an API to fetch data? Consider [Cube](https://cube.dev/?ref=eco-svelte-chartjs), an open-source API for data apps. 41 | 42 |
43 | 44 | [![supported by Cube](https://user-images.githubusercontent.com/986756/154330861-d79ab8ec-aacb-4af8-9e17-1b28f1eccb01.svg)](https://cube.dev/?ref=eco-svelte-chartjs) 45 | 46 | ## Usage 47 | 48 | ```svelte 49 | 52 | 53 | 54 | ``` 55 | 56 | ### Custom Size 57 | 58 | In order for Chart.js to obey the custom size you need to set `maintainAspectRatio` to false, example: 59 | 60 | ```svelte 61 | 67 | ``` 68 | 69 | ## Migration from v1 to v2 70 | 71 | With v2, this library introduces a number of breaking changes. In order to improve performance, offer new features, and improve maintainability, it was necessary to break backwards compatibility, but we aimed to do so only when worth the benefit. 72 | 73 | ### Change component import path 74 | 75 | v1: 76 | 77 | ```javascript 78 | import Line from 'svelte-chartjs/src/Line.svelte' 79 | ``` 80 | 81 | v2: 82 | 83 | ```javascript 84 | import { Line } from 'svelte-chartjs' 85 | ``` 86 | 87 | ### Tree-shaking 88 | 89 | v2 of this library, [just like Chart.js v3](https://www.chartjs.org/docs/latest/getting-started/v3-migration.html#setup-and-installation), is tree-shakable. It means that you need to import and register the controllers, elements, scales, and plugins you want to use. 90 | 91 | For a list of all the available items to import, see [Chart.js docs](https://www.chartjs.org/docs/latest/getting-started/integration.html#bundlers-webpack-rollup-etc). 92 | 93 | v1: 94 | 95 | ```javascript 96 | import Line from 'svelte-chartjs/src/Line.svelte' 97 | ``` 98 | 99 | v2 — lazy way: 100 | 101 | ```javascript 102 | import { Line } from 'svelte-chartjs' 103 | import 'chart.js/auto'; 104 | ``` 105 | 106 | v2 — tree-shakable way: 107 | 108 | ```javascript 109 | import { Line } from 'svelte-chartjs' 110 | import { Chart as ChartJS, Title, Tooltip, Legend, LineElement, LinearScale, PointElement, CategoryScale } from 'chart.js'; 111 | 112 | ChartJS.register(Title, Tooltip, Legend, LineElement, LinearScale, PointElement, CategoryScale); 113 | ``` 114 | 115 | Using the "lazy way" is okay to simplify the migration, but please consider using the tree-shakable way to decrease the bundle size. 116 | 117 | Please note that typed chart components register their controllers by default, so you don't need to register them by yourself. For example, when using the Pie component, you don't need to register PieController explicitly. 118 | 119 | ```javascript 120 | import { Pie } from 'svelte-chartjs'; 121 | import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale } from 'chart.js' 122 | 123 | ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale) 124 | ``` 125 | 126 | ## Examples 127 | 128 | - [Bar Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/bar) 129 | - [Bubble Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/bubble) 130 | - [Doughnut Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/doughnut) 131 | - [Line Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/line) 132 | - [Pie Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/pie) 133 | - [PolarArea Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/polar) 134 | - [Radar Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/radar) 135 | - [Scatter Chart](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/scatter) 136 | - [ChartJS instance](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/ref) 137 | - [Events handling](https://codesandbox.io/s/github/SauravKanchan/svelte-chartjs/tree/master/sandboxes/events) 138 | 139 | ## Docs for v1 140 | 141 | Full Documentation and demo for v1 [here](https://saurav.tech/mdbsvelte/?path=/story/charts--installation) 142 | ## License 143 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FSauravKanchan%2Fsvelte-chartjs.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2FSauravKanchan%2Fsvelte-chartjs?ref=badge_large) 144 | -------------------------------------------------------------------------------- /assets/svelte-chartjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SauravKanchan/svelte-chartjs/4333128d3f47b7e8c9a7a77177ad8592c2e22999/assets/svelte-chartjs.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-chartjs", 3 | "version": "3.1.5", 4 | "author": "Saurav Kanchan", 5 | "homepage": "https://saurav.tech/mdbsvelte/?path=/story/charts--examples", 6 | "license": "MIT", 7 | "keywords": [ 8 | "svelte", 9 | "chartjs" 10 | ], 11 | "type": "module", 12 | "types": "./dist/index.d.ts", 13 | "svelte": "./dist/index.js", 14 | "exports": { 15 | ".": { 16 | "types": "./dist/index.d.ts", 17 | "svelte": "./dist/index.js", 18 | "import": "./dist/index.js" 19 | }, 20 | "./package.json": "./package.json" 21 | }, 22 | "files": [ 23 | "dist", 24 | "src" 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/SauravKanchan/svelte-chartjs.git" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/SauravKanchan/svelte-chartjs" 32 | }, 33 | "scripts": { 34 | "build": "svelte-package --input ./src && pnpm lint:package", 35 | "commit": "cz", 36 | "format": "prettier --write 'src/**/*.{js,ts,svelte}'", 37 | "test:lint": "eslint src --ext .js,.svelte", 38 | "test:size": "size-limit", 39 | "test:unit": "vitest run --coverage", 40 | "test": "pnpm test:lint && pnpm test:unit", 41 | "lint:package": "publint --strict", 42 | "start:storybook": "storybook dev -p 6006", 43 | "build:storybook": "del ./storybook-static; NODE_ENV=production storybook build -o ./storybook-static", 44 | "bumpVersion": "standard-version", 45 | "createGithubRelease": "simple-github-release", 46 | "release": "pnpm bumpVersion && git push origin master --tags && pnpm createGithubRelease", 47 | "updateGitHooks": "simple-git-hooks" 48 | }, 49 | "peerDependencies": { 50 | "chart.js": "^3.5.0 || ^4.0.0", 51 | "svelte": "^4.0.0" 52 | }, 53 | "devDependencies": { 54 | "@commitlint/cli": "^18.0.0", 55 | "@commitlint/config-conventional": "^18.0.0", 56 | "@commitlint/cz-commitlint": "^18.0.0", 57 | "@size-limit/preset-big-lib": "^8.0.0", 58 | "@storybook/addon-actions": "^7.6.10", 59 | "@storybook/addon-backgrounds": "^7.6.10", 60 | "@storybook/addon-docs": "^7.6.10", 61 | "@storybook/addon-essentials": "^7.6.10", 62 | "@storybook/addon-measure": "^7.6.10", 63 | "@storybook/addon-outline": "^7.6.10", 64 | "@storybook/builder-vite": "^7.6.10", 65 | "@storybook/client-api": "^7.6.10", 66 | "@storybook/client-logger": "^7.6.10", 67 | "@storybook/svelte": "^7.6.10", 68 | "@storybook/svelte-vite": "^7.6.10", 69 | "@sveltejs/package": "^2.2.4", 70 | "@sveltejs/vite-plugin-svelte": "^3.0.2", 71 | "@testing-library/jest-dom": "^6.1.4", 72 | "@testing-library/svelte": "^4.0.5", 73 | "@tsconfig/svelte": "^5.0.2", 74 | "@types/node": "^20.11.10", 75 | "@typescript-eslint/eslint-plugin": "^7.0.0", 76 | "@typescript-eslint/parser": "^7.0.0", 77 | "@vitest/coverage-v8": "^1.2.2", 78 | "chart.js": "^4.1.2", 79 | "commitizen": "^4.2.4", 80 | "cz-conventional-changelog": "^3.3.0", 81 | "del-cli": "^5.0.0", 82 | "eslint": "^8.56.0", 83 | "eslint-plugin-import": "^2.29.1", 84 | "eslint-plugin-svelte": "^2.35.1", 85 | "eslint-plugin-vitest": "^0.3.20", 86 | "jsdom": "^24.0.0", 87 | "nano-staged": "^0.8.0", 88 | "prettier": "^3.1.0", 89 | "prettier-plugin-svelte": "^3.1.2", 90 | "publint": "^0.2.7", 91 | "react": "^18.2.0", 92 | "react-dom": "^18.2.0", 93 | "simple-git-hooks": "^2.8.0", 94 | "simple-github-release": "^1.0.0", 95 | "size-limit": "^8.0.0", 96 | "standard-version": "^9.5.0", 97 | "storybook": "^7.6.10", 98 | "svelte": "^4.2.9", 99 | "svelte-eslint-parser": "^0.33.1", 100 | "svelte-loader": "^3.1.9", 101 | "svelte-preprocess": "^5.1.3", 102 | "typescript": "^5.0.0", 103 | "vite": "^5.0.12", 104 | "vitest": "^1.2.1", 105 | "vitest-canvas-mock": "^0.3.3" 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /sandboxes/bar/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/bar/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /sandboxes/bar/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], 3 | datasets: [ 4 | { 5 | label: '% of Votes', 6 | data: [12, 19, 3, 5, 2, 3], 7 | backgroundColor: [ 8 | 'rgba(255, 134,159,0.4)', 9 | 'rgba(98, 182, 239,0.4)', 10 | 'rgba(255, 218, 128,0.4)', 11 | 'rgba(113, 205, 205,0.4)', 12 | 'rgba(170, 128, 252,0.4)', 13 | 'rgba(255, 177, 101,0.4)', 14 | ], 15 | borderWidth: 2, 16 | borderColor: [ 17 | 'rgba(255, 134, 159, 1)', 18 | 'rgba(98, 182, 239, 1)', 19 | 'rgba(255, 218, 128, 1)', 20 | 'rgba(113, 205, 205, 1)', 21 | 'rgba(170, 128, 252, 1)', 22 | 'rgba(255, 177, 101, 1)', 23 | ], 24 | }, 25 | ], 26 | }; 27 | -------------------------------------------------------------------------------- /sandboxes/bar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/bar/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/bar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bar-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/bar/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/bubble/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/bubble/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /sandboxes/bubble/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | labels: 'Bubble', 3 | datasets: [ 4 | { 5 | label: 'John', 6 | data: [ 7 | { 8 | x: 3, 9 | y: 7, 10 | r: 10, 11 | }, 12 | ], 13 | backgroundColor: '#ff6384', 14 | hoverBackgroundColor: '#ff6384', 15 | }, 16 | { 17 | label: 'Peter', 18 | data: [ 19 | { 20 | x: 3.2, 21 | y: 7, 22 | r: 10, 23 | }, 24 | ], 25 | backgroundColor: '#44e4ee', 26 | hoverBackgroundColor: '#44e4ee', 27 | }, 28 | { 29 | label: 'Donald', 30 | data: [ 31 | { 32 | x: 3.4, 33 | y: 7, 34 | r: 10, 35 | }, 36 | ], 37 | backgroundColor: '#62088A', 38 | hoverBackgroundColor: '#62088A', 39 | }, 40 | ], 41 | }; 42 | -------------------------------------------------------------------------------- /sandboxes/bubble/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/bubble/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/bubble/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bubble-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/bubble/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/doughnut/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/doughnut/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /sandboxes/doughnut/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | labels: ['Red', 'Green', 'Yellow', 'Grey', 'Dark Grey'], 3 | datasets: [ 4 | { 5 | data: [300, 50, 100, 40, 120], 6 | backgroundColor: ['#F7464A', '#46BFBD', '#FDB45C', '#949FB1', '#4D5360'], 7 | hoverBackgroundColor: [ 8 | '#FF5A5E', 9 | '#5AD3D1', 10 | '#FFC870', 11 | '#A8B3C5', 12 | '#616774', 13 | ], 14 | }, 15 | ], 16 | }; 17 | -------------------------------------------------------------------------------- /sandboxes/doughnut/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/doughnut/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/doughnut/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "doughnut-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/doughnut/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/events/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/events/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /sandboxes/events/components/data.js: -------------------------------------------------------------------------------- 1 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July']; 2 | 3 | export const data = { 4 | labels, 5 | datasets: [ 6 | { 7 | type: 'line', 8 | label: 'Dataset 1', 9 | borderColor: 'rgb(255, 99, 132)', 10 | borderWidth: 2, 11 | fill: false, 12 | data: labels.map(() => Math.random() * 1000), 13 | }, 14 | { 15 | type: 'bar', 16 | label: 'Dataset 2', 17 | backgroundColor: 'rgb(75, 192, 192)', 18 | data: labels.map(() => Math.random() * 1000), 19 | borderColor: 'white', 20 | borderWidth: 2, 21 | }, 22 | { 23 | type: 'bar', 24 | label: 'Dataset 3', 25 | backgroundColor: 'rgb(53, 162, 235)', 26 | data: labels.map(() => Math.random() * 1000), 27 | }, 28 | ], 29 | }; 30 | 31 | export const options = { 32 | scales: { 33 | y: { 34 | beginAtZero: true, 35 | }, 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /sandboxes/events/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/events/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/events/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "events", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/events/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/line/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/line/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /sandboxes/line/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], 3 | datasets: [ 4 | { 5 | label: 'My First dataset', 6 | fill: true, 7 | lineTension: 0.3, 8 | backgroundColor: 'rgba(225, 204,230, .3)', 9 | borderColor: 'rgb(205, 130, 158)', 10 | borderCapStyle: 'butt', 11 | borderDash: [], 12 | borderDashOffset: 0.0, 13 | borderJoinStyle: 'miter', 14 | pointBorderColor: 'rgb(205, 130,1 58)', 15 | pointBackgroundColor: 'rgb(255, 255, 255)', 16 | pointBorderWidth: 10, 17 | pointHoverRadius: 5, 18 | pointHoverBackgroundColor: 'rgb(0, 0, 0)', 19 | pointHoverBorderColor: 'rgba(220, 220, 220,1)', 20 | pointHoverBorderWidth: 2, 21 | pointRadius: 1, 22 | pointHitRadius: 10, 23 | data: [65, 59, 80, 81, 56, 55, 40], 24 | }, 25 | { 26 | label: 'My Second dataset', 27 | fill: true, 28 | lineTension: 0.3, 29 | backgroundColor: 'rgba(184, 185, 210, .3)', 30 | borderColor: 'rgb(35, 26, 136)', 31 | borderCapStyle: 'butt', 32 | borderDash: [], 33 | borderDashOffset: 0.0, 34 | borderJoinStyle: 'miter', 35 | pointBorderColor: 'rgb(35, 26, 136)', 36 | pointBackgroundColor: 'rgb(255, 255, 255)', 37 | pointBorderWidth: 10, 38 | pointHoverRadius: 5, 39 | pointHoverBackgroundColor: 'rgb(0, 0, 0)', 40 | pointHoverBorderColor: 'rgba(220, 220, 220, 1)', 41 | pointHoverBorderWidth: 2, 42 | pointRadius: 1, 43 | pointHitRadius: 10, 44 | data: [28, 48, 40, 19, 86, 27, 90], 45 | }, 46 | ], 47 | }; 48 | -------------------------------------------------------------------------------- /sandboxes/line/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/line/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/line/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "line-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/line/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/pie/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/pie/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /sandboxes/pie/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | labels: ['Red', 'Green', 'Yellow', 'Grey', 'Dark Grey'], 3 | datasets: [ 4 | { 5 | data: [300, 50, 100, 40, 120], 6 | backgroundColor: [ 7 | '#F7464A', 8 | '#46BFBD', 9 | '#FDB45C', 10 | '#949FB1', 11 | '#4D5360', 12 | '#AC64AD', 13 | ], 14 | hoverBackgroundColor: [ 15 | '#FF5A5E', 16 | '#5AD3D1', 17 | '#FFC870', 18 | '#A8B3C5', 19 | '#616774', 20 | '#DA92DB', 21 | ], 22 | }, 23 | ], 24 | }; 25 | -------------------------------------------------------------------------------- /sandboxes/pie/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/pie/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/pie/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pie-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/polar/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/polar/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /sandboxes/polar/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | datasets: [ 3 | { 4 | data: [300, 50, 100, 40, 120], 5 | backgroundColor: [ 6 | 'rgba(247, 70, 74, 0.5)', 7 | 'rgba(70, 191, 189, 0.5)', 8 | 'rgba(253, 180, 92, 0.5)', 9 | 'rgba(148, 159, 177, 0.5)', 10 | 'rgba(77, 83, 96, 0.5)', 11 | ], 12 | label: 'My dataset', // for legend 13 | }, 14 | ], 15 | labels: ['Red', 'Green', 'Yellow', 'Grey', 'Dark Grey'], 16 | }; 17 | -------------------------------------------------------------------------------- /sandboxes/polar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/polar/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/polar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polar-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/polar/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/radar/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/radar/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /sandboxes/radar/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | labels: [ 3 | 'Eating', 4 | 'Drinking', 5 | 'Sleeping', 6 | 'Designing', 7 | 'Coding', 8 | 'Cycling', 9 | 'Running', 10 | ], 11 | datasets: [ 12 | { 13 | label: 'My First dataset', 14 | backgroundColor: 'rgba(194, 116, 161, 0.5)', 15 | borderColor: 'rgb(194, 116, 161)', 16 | data: [65, 59, 90, 81, 56, 55, 40], 17 | }, 18 | { 19 | label: 'My Second dataset', 20 | backgroundColor: 'rgba(71, 225, 167, 0.5)', 21 | borderColor: 'rgb(71, 225, 167)', 22 | data: [28, 48, 40, 19, 96, 27, 100], 23 | }, 24 | ], 25 | }; 26 | -------------------------------------------------------------------------------- /sandboxes/radar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/radar/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/radar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "radar-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/radar/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/ref/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/ref/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /sandboxes/ref/components/data.js: -------------------------------------------------------------------------------- 1 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July']; 2 | 3 | export const data = { 4 | labels, 5 | datasets: [ 6 | { 7 | type: 'line', 8 | label: 'Dataset 1', 9 | borderColor: 'rgb(255, 99, 132)', 10 | borderWidth: 2, 11 | fill: false, 12 | data: labels.map(() => Math.random() * 1000), 13 | }, 14 | { 15 | type: 'bar', 16 | label: 'Dataset 2', 17 | backgroundColor: 'rgb(75, 192, 192)', 18 | data: labels.map(() => Math.random() * 1000), 19 | borderColor: 'white', 20 | borderWidth: 2, 21 | }, 22 | { 23 | type: 'bar', 24 | label: 'Dataset 3', 25 | backgroundColor: 'rgb(53, 162, 235)', 26 | data: labels.map(() => Math.random() * 1000), 27 | }, 28 | ], 29 | }; 30 | 31 | export const options = { 32 | scales: { 33 | y: { 34 | beginAtZero: true, 35 | }, 36 | }, 37 | }; 38 | -------------------------------------------------------------------------------- /sandboxes/ref/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/ref/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/ref/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "events", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/ref/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /sandboxes/scatter/App.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /sandboxes/scatter/components/Chart.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /sandboxes/scatter/components/data.js: -------------------------------------------------------------------------------- 1 | export const data = { 2 | labels: ['Scatter'], 3 | datasets: [ 4 | { 5 | borderColor: 'rgba(99,0,125, .2)', 6 | backgroundColor: 'rgba(99,0,125, .5)', 7 | label: 'V(node2)', 8 | data: [ 9 | { 10 | x: 1, 11 | y: -1.711e-2, 12 | }, 13 | { 14 | x: 1.26, 15 | y: -2.708e-2, 16 | }, 17 | { 18 | x: 1.58, 19 | y: -4.285e-2, 20 | }, 21 | { 22 | x: 2.0, 23 | y: -6.772e-2, 24 | }, 25 | { 26 | x: 2.51, 27 | y: -1.068e-1, 28 | }, 29 | { 30 | x: 3.16, 31 | y: -1.681e-1, 32 | }, 33 | { 34 | x: 3.98, 35 | y: -2.635e-1, 36 | }, 37 | { 38 | x: 5.01, 39 | y: -4.106e-1, 40 | }, 41 | { 42 | x: 6.31, 43 | y: -6.339e-1, 44 | }, 45 | { 46 | x: 7.94, 47 | y: -9.659e-1, 48 | }, 49 | { 50 | x: 10.0, 51 | y: -1.445, 52 | }, 53 | { 54 | x: 12.6, 55 | y: -2.11, 56 | }, 57 | { 58 | x: 15.8, 59 | y: -2.992, 60 | }, 61 | { 62 | x: 20.0, 63 | y: -4.102, 64 | }, 65 | { 66 | x: 25.1, 67 | y: -5.429, 68 | }, 69 | { 70 | x: 31.6, 71 | y: -6.944, 72 | }, 73 | { 74 | x: 39.8, 75 | y: -8.607, 76 | }, 77 | { 78 | x: 50.1, 79 | y: -1.038e1, 80 | }, 81 | { 82 | x: 63.1, 83 | y: -1.223e1, 84 | }, 85 | { 86 | x: 79.4, 87 | y: -1.413e1, 88 | }, 89 | { 90 | x: 100.0, 91 | y: -1.607e1, 92 | }, 93 | { 94 | x: 126, 95 | y: -1.803e1, 96 | }, 97 | { 98 | x: 158, 99 | y: -2e1, 100 | }, 101 | { 102 | x: 200, 103 | y: -2.199e1, 104 | }, 105 | { 106 | x: 251, 107 | y: -2.398e1, 108 | }, 109 | { 110 | x: 316, 111 | y: -2.597e1, 112 | }, 113 | { 114 | x: 398, 115 | y: -2.797e1, 116 | }, 117 | { 118 | x: 501, 119 | y: -2.996e1, 120 | }, 121 | { 122 | x: 631, 123 | y: -3.196e1, 124 | }, 125 | { 126 | x: 794, 127 | y: -3.396e1, 128 | }, 129 | { 130 | x: 1000, 131 | y: -3.596e1, 132 | }, 133 | ], 134 | }, 135 | ], 136 | }; 137 | -------------------------------------------------------------------------------- /sandboxes/scatter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sandboxes/scatter/index.js: -------------------------------------------------------------------------------- 1 | import App from './App.svelte'; 2 | 3 | const app = new App({ 4 | target: document.body, 5 | }); 6 | 7 | export default app; 8 | -------------------------------------------------------------------------------- /sandboxes/scatter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scatter-chart", 3 | "type": "module", 4 | "scripts": { 5 | "start": "vite" 6 | }, 7 | "dependencies": { 8 | "svelte": "^4.0.0", 9 | "svelte-chartjs": "^3.0.0", 10 | "chart.js": "^4.0.0" 11 | }, 12 | "devDependencies": { 13 | "@sveltejs/vite-plugin-svelte": "^3.0.0", 14 | "vite": "^5.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sandboxes/scatter/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | }); 7 | -------------------------------------------------------------------------------- /src/Bar.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Bubble.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Chart.svelte: -------------------------------------------------------------------------------- 1 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/Doughnut.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Line.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Pie.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/PolarArea.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Radar.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/Scatter.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import Chart from './Chart.svelte'; 2 | import Line from './Line.svelte'; 3 | import Radar from './Radar.svelte'; 4 | import Doughnut from './Doughnut.svelte'; 5 | import Pie from './Pie.svelte'; 6 | import Bar from './Bar.svelte'; 7 | import PolarArea from './PolarArea.svelte'; 8 | import Bubble from './Bubble.svelte'; 9 | import Scatter from './Scatter.svelte'; 10 | 11 | /** 12 | * @deprecated Please use `Chart` name instead. 13 | * @todo Remove in v3.0.0 14 | */ 15 | const Base = Chart; 16 | /** 17 | * @deprecated Please use `PolarArea` name instead. 18 | * @todo Remove in v3.0.0 19 | */ 20 | const Polar = PolarArea; 21 | 22 | export * from './types/index.js'; 23 | export * from './utils/index.js'; 24 | export { 25 | Chart, 26 | Base, 27 | Line, 28 | Radar, 29 | Doughnut, 30 | Pie, 31 | Bar, 32 | Scatter, 33 | Bubble, 34 | PolarArea, 35 | Polar, 36 | }; 37 | -------------------------------------------------------------------------------- /src/types/chart.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | ChartType, 3 | ChartData, 4 | ChartOptions, 5 | DefaultDataPoint, 6 | Plugin, 7 | UpdateMode, 8 | } from 'chart.js'; 9 | import type { HTMLAttributes } from './html.js'; 10 | 11 | export interface ChartBaseProps< 12 | TType extends ChartType = ChartType, 13 | TData = DefaultDataPoint, 14 | TLabel = unknown 15 | > extends Omit { 16 | /** 17 | * Chart.js chart type 18 | */ 19 | type: TType; 20 | /** 21 | * The data object that is passed into the Chart.js chart 22 | * @see https://www.chartjs.org/docs/latest/getting-started/ 23 | */ 24 | data: ChartData; 25 | /** 26 | * The options object that is passed into the Chart.js chart 27 | * @see https://www.chartjs.org/docs/latest/general/options.html 28 | * @default {} 29 | */ 30 | options?: ChartOptions; 31 | /** 32 | * The plugins array that is passed into the Chart.js chart 33 | * @see https://www.chartjs.org/docs/latest/developers/plugins.html 34 | * @default [] 35 | */ 36 | plugins?: Plugin[]; 37 | /** 38 | * A mode string to indicate transition configuration should be used. 39 | * @see https://www.chartjs.org/docs/latest/developers/api.html#update-mode 40 | */ 41 | updateMode?: UpdateMode; 42 | } 43 | -------------------------------------------------------------------------------- /src/types/html.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Adapted from jsx-dom 3 | * @see https://github.com/proteriax/jsx-dom/blob/be06937ba16908d87bf8aa4372a3583133e02b8a/index.d.ts 4 | * 5 | * which was adapted from 6 | * 7 | * Adapted from React’s TypeScript definition from DefinitelyTyped. 8 | * @see https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts 9 | */ 10 | /* eslint-disable @typescript-eslint/no-explicit-any */ 11 | 12 | // All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/ 13 | interface AriaAttributes { 14 | /** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */ 15 | 'aria-activedescendant'?: string | undefined | null; 16 | /** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */ 17 | 'aria-atomic'?: boolean | 'false' | 'true' | undefined | null; 18 | /** 19 | * Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be 20 | * presented if they are made. 21 | */ 22 | 'aria-autocomplete'?: 'none' | 'inline' | 'list' | 'both' | undefined | null; 23 | /** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */ 24 | 'aria-busy'?: boolean | 'false' | 'true' | undefined | null; 25 | /** 26 | * Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. 27 | * @see aria-pressed @see aria-selected. 28 | */ 29 | 'aria-checked'?: boolean | 'false' | 'mixed' | 'true' | undefined | null; 30 | /** 31 | * Defines the total number of columns in a table, grid, or treegrid. 32 | * @see aria-colindex. 33 | */ 34 | 'aria-colcount'?: number | undefined | null; 35 | /** 36 | * Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. 37 | * @see aria-colcount @see aria-colspan. 38 | */ 39 | 'aria-colindex'?: number | undefined | null; 40 | /** 41 | * Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. 42 | * @see aria-colindex @see aria-rowspan. 43 | */ 44 | 'aria-colspan'?: number | undefined | null; 45 | /** 46 | * Identifies the element (or elements) whose contents or presence are controlled by the current element. 47 | * @see aria-owns. 48 | */ 49 | 'aria-controls'?: string | undefined | null; 50 | /** Indicates the element that represents the current item within a container or set of related elements. */ 51 | 'aria-current'?: 52 | | boolean 53 | | 'false' 54 | | 'true' 55 | | 'page' 56 | | 'step' 57 | | 'location' 58 | | 'date' 59 | | 'time' 60 | | undefined 61 | | null; 62 | /** 63 | * Identifies the element (or elements) that describes the object. 64 | * @see aria-labelledby 65 | */ 66 | 'aria-describedby'?: string | undefined | null; 67 | /** 68 | * Identifies the element that provides a detailed, extended description for the object. 69 | * @see aria-describedby. 70 | */ 71 | 'aria-details'?: string | undefined | null; 72 | /** 73 | * Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable. 74 | * @see aria-hidden @see aria-readonly. 75 | */ 76 | 'aria-disabled'?: boolean | 'false' | 'true' | undefined | null; 77 | /** 78 | * Indicates what functions can be performed when a dragged object is released on the drop target. 79 | * @deprecated in ARIA 1.1 80 | */ 81 | 'aria-dropeffect'?: 82 | | 'none' 83 | | 'copy' 84 | | 'execute' 85 | | 'link' 86 | | 'move' 87 | | 'popup' 88 | | undefined 89 | | null; 90 | /** 91 | * Identifies the element that provides an error message for the object. 92 | * @see aria-invalid @see aria-describedby. 93 | */ 94 | 'aria-errormessage'?: string | undefined | null; 95 | /** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */ 96 | 'aria-expanded'?: boolean | 'false' | 'true' | undefined | null; 97 | /** 98 | * Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, 99 | * allows assistive technology to override the general default of reading in document source order. 100 | */ 101 | 'aria-flowto'?: string | undefined | null; 102 | /** 103 | * Indicates an element's "grabbed" state in a drag-and-drop operation. 104 | * @deprecated in ARIA 1.1 105 | */ 106 | 'aria-grabbed'?: boolean | 'false' | 'true' | undefined | null; 107 | /** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */ 108 | 'aria-haspopup'?: 109 | | boolean 110 | | 'false' 111 | | 'true' 112 | | 'menu' 113 | | 'listbox' 114 | | 'tree' 115 | | 'grid' 116 | | 'dialog' 117 | | undefined 118 | | null; 119 | /** 120 | * Indicates whether the element is exposed to an accessibility API. 121 | * @see aria-disabled. 122 | */ 123 | 'aria-hidden'?: boolean | 'false' | 'true' | undefined | null; 124 | /** 125 | * Indicates the entered value does not conform to the format expected by the application. 126 | * @see aria-errormessage. 127 | */ 128 | 'aria-invalid'?: 129 | | boolean 130 | | 'false' 131 | | 'true' 132 | | 'grammar' 133 | | 'spelling' 134 | | undefined 135 | | null; 136 | /** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */ 137 | 'aria-keyshortcuts'?: string | undefined | null; 138 | /** 139 | * Defines a string value that labels the current element. 140 | * @see aria-labelledby. 141 | */ 142 | 'aria-label'?: string | undefined | null; 143 | /** 144 | * Identifies the element (or elements) that labels the current element. 145 | * @see aria-describedby. 146 | */ 147 | 'aria-labelledby'?: string | undefined | null; 148 | /** Defines the hierarchical level of an element within a structure. */ 149 | 'aria-level'?: number | undefined | null; 150 | /** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */ 151 | 'aria-live'?: 'off' | 'assertive' | 'polite' | undefined | null; 152 | /** Indicates whether an element is modal when displayed. */ 153 | 'aria-modal'?: boolean | 'false' | 'true' | undefined | null; 154 | /** Indicates whether a text box accepts multiple lines of input or only a single line. */ 155 | 'aria-multiline'?: boolean | 'false' | 'true' | undefined | null; 156 | /** Indicates that the user may select more than one item from the current selectable descendants. */ 157 | 'aria-multiselectable'?: boolean | 'false' | 'true' | undefined | null; 158 | /** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */ 159 | 'aria-orientation'?: 'horizontal' | 'vertical' | undefined | null; 160 | /** 161 | * Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship 162 | * between DOM elements where the DOM hierarchy cannot be used to represent the relationship. 163 | * @see aria-controls. 164 | */ 165 | 'aria-owns'?: string | undefined | null; 166 | /** 167 | * Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. 168 | * A hint could be a sample value or a brief description of the expected format. 169 | */ 170 | 'aria-placeholder'?: string | undefined | null; 171 | /** 172 | * Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. 173 | * @see aria-setsize. 174 | */ 175 | 'aria-posinset'?: number | undefined | null; 176 | /** 177 | * Indicates the current "pressed" state of toggle buttons. 178 | * @see aria-checked @see aria-selected. 179 | */ 180 | 'aria-pressed'?: boolean | 'false' | 'mixed' | 'true' | undefined | null; 181 | /** 182 | * Indicates that the element is not editable, but is otherwise operable. 183 | * @see aria-disabled. 184 | */ 185 | 'aria-readonly'?: boolean | 'false' | 'true' | undefined | null; 186 | /** 187 | * Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. 188 | * @see aria-atomic. 189 | */ 190 | 'aria-relevant'?: 191 | | 'additions' 192 | | 'additions removals' 193 | | 'additions text' 194 | | 'all' 195 | | 'removals' 196 | | 'removals additions' 197 | | 'removals text' 198 | | 'text' 199 | | 'text additions' 200 | | 'text removals' 201 | | undefined 202 | | null; 203 | /** Indicates that user input is required on the element before a form may be submitted. */ 204 | 'aria-required'?: boolean | 'false' | 'true' | undefined | null; 205 | /** Defines a human-readable, author-localized description for the role of an element. */ 206 | 'aria-roledescription'?: string | undefined | null; 207 | /** 208 | * Defines the total number of rows in a table, grid, or treegrid. 209 | * @see aria-rowindex. 210 | */ 211 | 'aria-rowcount'?: number | undefined | null; 212 | /** 213 | * Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. 214 | * @see aria-rowcount @see aria-rowspan. 215 | */ 216 | 'aria-rowindex'?: number | undefined | null; 217 | /** 218 | * Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. 219 | * @see aria-rowindex @see aria-colspan. 220 | */ 221 | 'aria-rowspan'?: number | undefined | null; 222 | /** 223 | * Indicates the current "selected" state of various widgets. 224 | * @see aria-checked @see aria-pressed. 225 | */ 226 | 'aria-selected'?: boolean | 'false' | 'true' | undefined | null; 227 | /** 228 | * Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. 229 | * @see aria-posinset. 230 | */ 231 | 'aria-setsize'?: number | undefined | null; 232 | /** Indicates if items in a table or grid are sorted in ascending or descending order. */ 233 | 'aria-sort'?: 234 | | 'none' 235 | | 'ascending' 236 | | 'descending' 237 | | 'other' 238 | | undefined 239 | | null; 240 | /** Defines the maximum allowed value for a range widget. */ 241 | 'aria-valuemax'?: number | undefined | null; 242 | /** Defines the minimum allowed value for a range widget. */ 243 | 'aria-valuemin'?: number | undefined | null; 244 | /** 245 | * Defines the current value for a range widget. 246 | * @see aria-valuetext. 247 | */ 248 | 'aria-valuenow'?: number | undefined | null; 249 | /** Defines the human readable text alternative of aria-valuenow for a range widget. */ 250 | 'aria-valuetext'?: string | undefined | null; 251 | } 252 | 253 | export interface HTMLAttributes extends AriaAttributes { 254 | // Standard HTML Attributes 255 | class?: string | undefined | null; 256 | dataset?: object | undefined | null; // eslint-disable-line 257 | accept?: string | undefined | null; 258 | acceptcharset?: string | undefined | null; 259 | accesskey?: string | undefined | null; 260 | action?: string | undefined | null; 261 | allow?: string | undefined | null; 262 | allowfullscreen?: boolean | undefined | null; 263 | allowtransparency?: boolean | undefined | null; 264 | allowpaymentrequest?: boolean | undefined | null; 265 | alt?: string | undefined | null; 266 | as?: string | undefined | null; 267 | async?: boolean | undefined | null; 268 | autocomplete?: string | undefined | null; 269 | autofocus?: boolean | undefined | null; 270 | autoplay?: boolean | undefined | null; 271 | capture?: 'environment' | 'user' | boolean | undefined | null; 272 | cellpadding?: number | string | undefined | null; 273 | cellspacing?: number | string | undefined | null; 274 | charset?: string | undefined | null; 275 | challenge?: string | undefined | null; 276 | checked?: boolean | undefined | null; 277 | cite?: string | undefined | null; 278 | classid?: string | undefined | null; 279 | cols?: number | undefined | null; 280 | colspan?: number | undefined | null; 281 | content?: string | undefined | null; 282 | contenteditable?: 'true' | 'false' | boolean | undefined | null; 283 | 284 | // Doesn't work when used as HTML attribute 285 | /** 286 | * Elements with the contenteditable attribute support innerHTML and textContent bindings. 287 | */ 288 | innerHTML?: string | undefined | null; 289 | // Doesn't work when used as HTML attribute 290 | /** 291 | * Elements with the contenteditable attribute support innerHTML and textContent bindings. 292 | */ 293 | 294 | textContent?: string | undefined | null; 295 | 296 | contextmenu?: string | undefined | null; 297 | controls?: boolean | undefined | null; 298 | coords?: string | undefined | null; 299 | crossorigin?: string | undefined | null; 300 | currenttime?: number | undefined | null; 301 | decoding?: 'async' | 'sync' | 'auto' | undefined | null; 302 | data?: string | undefined | null; 303 | datetime?: string | undefined | null; 304 | default?: boolean | undefined | null; 305 | defaultmuted?: boolean | undefined | null; 306 | defaultplaybackrate?: number | undefined | null; 307 | defer?: boolean | undefined | null; 308 | dir?: string | undefined | null; 309 | dirname?: string | undefined | null; 310 | disabled?: boolean | undefined | null; 311 | download?: any | undefined | null; 312 | draggable?: boolean | 'true' | 'false' | undefined | null; 313 | enctype?: string | undefined | null; 314 | enterkeyhint?: 315 | | 'enter' 316 | | 'done' 317 | | 'go' 318 | | 'next' 319 | | 'previous' 320 | | 'search' 321 | | 'send' 322 | | undefined 323 | | null; 324 | for?: string | undefined | null; 325 | form?: string | undefined | null; 326 | formaction?: string | undefined | null; 327 | formenctype?: string | undefined | null; 328 | formmethod?: string | undefined | null; 329 | formnovalidate?: boolean | undefined | null; 330 | formtarget?: string | undefined | null; 331 | frameborder?: number | string | undefined | null; 332 | headers?: string | undefined | null; 333 | height?: number | string | undefined | null; 334 | hidden?: boolean | undefined | null; 335 | high?: number | undefined | null; 336 | href?: string | undefined | null; 337 | hreflang?: string | undefined | null; 338 | htmlfor?: string | undefined | null; 339 | httpequiv?: string | undefined | null; 340 | id?: string | undefined | null; 341 | inputmode?: string | undefined | null; 342 | integrity?: string | undefined | null; 343 | is?: string | undefined | null; 344 | ismap?: boolean | undefined | null; 345 | keyparams?: string | undefined | null; 346 | keytype?: string | undefined | null; 347 | kind?: string | undefined | null; 348 | label?: string | undefined | null; 349 | lang?: string | undefined | null; 350 | list?: string | undefined | null; 351 | loading?: string | undefined | null; 352 | loop?: boolean | undefined | null; 353 | low?: number | undefined | null; 354 | manifest?: string | undefined | null; 355 | marginheight?: number | undefined | null; 356 | marginwidth?: number | undefined | null; 357 | max?: number | string | undefined | null; 358 | maxlength?: number | undefined | null; 359 | media?: string | undefined | null; 360 | mediagroup?: string | undefined | null; 361 | method?: string | undefined | null; 362 | min?: number | string | undefined | null; 363 | minlength?: number | undefined | null; 364 | multiple?: boolean | undefined | null; 365 | muted?: boolean | undefined | null; 366 | name?: string | undefined | null; 367 | nonce?: string | undefined | null; 368 | novalidate?: boolean | undefined | null; 369 | open?: boolean | undefined | null; 370 | optimum?: number | undefined | null; 371 | part?: string | undefined | null; 372 | pattern?: string | undefined | null; 373 | placeholder?: string | undefined | null; 374 | playsinline?: boolean | undefined | null; 375 | ping?: string | undefined | null; 376 | poster?: string | undefined | null; 377 | preload?: string | undefined | null; 378 | radiogroup?: string | undefined | null; 379 | readonly?: boolean | undefined | null; 380 | referrerpolicy?: string | undefined | null; 381 | rel?: string | undefined | null; 382 | required?: boolean | undefined | null; 383 | reversed?: boolean | undefined | null; 384 | role?: string | undefined | null; 385 | rows?: number | undefined | null; 386 | rowspan?: number | undefined | null; 387 | sandbox?: string | undefined | null; 388 | scope?: string | undefined | null; 389 | scoped?: boolean | undefined | null; 390 | scrolling?: string | undefined | null; 391 | seamless?: boolean | undefined | null; 392 | selected?: boolean | undefined | null; 393 | shape?: string | undefined | null; 394 | size?: number | undefined | null; 395 | sizes?: string | undefined | null; 396 | slot?: string | undefined | null; 397 | span?: number | undefined | null; 398 | spellcheck?: boolean | 'true' | 'false' | undefined | null; 399 | src?: string | undefined | null; 400 | srcdoc?: string | undefined | null; 401 | srclang?: string | undefined | null; 402 | srcset?: string | undefined | null; 403 | start?: number | undefined | null; 404 | step?: number | string | undefined | null; 405 | style?: string | undefined | null; 406 | summary?: string | undefined | null; 407 | tabindex?: number | undefined | null; 408 | target?: string | undefined | null; 409 | title?: string | undefined | null; 410 | translate?: 'yes' | 'no' | '' | undefined | null; 411 | type?: string | undefined | null; 412 | usemap?: string | undefined | null; 413 | value?: any | undefined | null; 414 | /** 415 | * a value between 0 and 1 416 | */ 417 | volume?: number | undefined | null; 418 | width?: number | string | undefined | null; 419 | wmode?: string | undefined | null; 420 | wrap?: string | undefined | null; 421 | 422 | // RDFa Attributes 423 | about?: string | undefined | null; 424 | datatype?: string | undefined | null; 425 | inlist?: any | undefined | null; 426 | prefix?: string | undefined | null; 427 | property?: string | undefined | null; 428 | resource?: string | undefined | null; 429 | typeof?: string | undefined | null; 430 | vocab?: string | undefined | null; 431 | 432 | // Non-standard Attributes 433 | autocapitalize?: string | undefined | null; 434 | autocorrect?: string | undefined | null; 435 | autosave?: string | undefined | null; 436 | color?: string | undefined | null; 437 | controlslist?: 438 | | 'nodownload' 439 | | 'nofullscreen' 440 | | 'noplaybackrate' 441 | | 'noremoteplayback'; 442 | inert?: boolean | undefined | null; 443 | itemprop?: string | undefined | null; 444 | itemscope?: boolean | undefined | null; 445 | itemtype?: string | undefined | null; 446 | itemid?: string | undefined | null; 447 | itemref?: string | undefined | null; 448 | results?: number | undefined | null; 449 | security?: string | undefined | null; 450 | unselectable?: boolean | undefined | null; 451 | } 452 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './chart.js'; 2 | export * from './html.js'; 3 | -------------------------------------------------------------------------------- /src/utils/events.ts: -------------------------------------------------------------------------------- 1 | import type { Chart } from 'chart.js'; 2 | 3 | /** 4 | * Get dataset from mouse click event 5 | * @param chart - Chart.js instance 6 | * @param event - Mouse click event 7 | * @returns Dataset 8 | */ 9 | export function getDatasetAtEvent(chart: Chart, event: PointerEvent) { 10 | return chart.getElementsAtEventForMode( 11 | event, 12 | 'dataset', 13 | { intersect: true }, 14 | false 15 | ); 16 | } 17 | 18 | /** 19 | * Get single dataset element from mouse click event 20 | * @param chart - Chart.js instance 21 | * @param event - Mouse click event 22 | * @returns Dataset 23 | */ 24 | export function getElementAtEvent(chart: Chart, event: PointerEvent) { 25 | return chart.getElementsAtEventForMode( 26 | event, 27 | 'nearest', 28 | { intersect: true }, 29 | false 30 | ); 31 | } 32 | 33 | /** 34 | * Get all dataset elements from mouse click event 35 | * @param chart - Chart.js instance 36 | * @param event - Mouse click event 37 | * @returns Dataset 38 | */ 39 | export function getElementsAtEvent(chart: Chart, event: PointerEvent) { 40 | return chart.getElementsAtEventForMode( 41 | event, 42 | 'index', 43 | { intersect: true }, 44 | false 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './svelte.js'; 2 | export * from './events.js'; 3 | -------------------------------------------------------------------------------- /src/utils/svelte.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SvelteComponent, 3 | bubble, 4 | listen, 5 | current_component, 6 | } from 'svelte/internal'; 7 | import { onMount, onDestroy } from 'svelte'; 8 | 9 | const eventPrefix = /^on/; 10 | const events: string[] = []; 11 | 12 | Object.keys(globalThis).forEach(key => { 13 | if (eventPrefix.test(key)) { 14 | events.push(key.replace(eventPrefix, '')); 15 | } 16 | }); 17 | 18 | export function useForwardEvents( 19 | getRef: () => T 20 | ) { 21 | const component = current_component; 22 | const destructors: (() => void)[] = []; 23 | 24 | function forward(e) { 25 | bubble(component, e); 26 | } 27 | 28 | onMount(() => { 29 | const ref = getRef(); 30 | 31 | events.forEach( 32 | ref instanceof Element 33 | ? event => destructors.push(listen(ref, event, forward)) 34 | : event => destructors.push(ref.$on(event, forward)) 35 | ); 36 | }); 37 | 38 | onDestroy(() => { 39 | while (destructors.length) { 40 | destructors.pop()(); 41 | } 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /stories/bar.stories.ts: -------------------------------------------------------------------------------- 1 | import { Bar } from '../src'; 2 | import DefaultExample from '../sandboxes/bar/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'Bar', 6 | component: Bar, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /stories/bubble.stories.ts: -------------------------------------------------------------------------------- 1 | import { Bubble } from '../src'; 2 | import DefaultExample from '../sandboxes/bubble/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'Bubble', 6 | component: Bubble, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /stories/chart.stories.ts: -------------------------------------------------------------------------------- 1 | import { Chart } from '../src'; 2 | import RefExample from '../sandboxes/ref/components/Chart.svelte'; 3 | import EventsExample from '../sandboxes/events/components/Chart.svelte'; 4 | 5 | export default { 6 | title: 'Chart', 7 | component: Chart, 8 | parameters: { 9 | layout: 'centered', 10 | }, 11 | }; 12 | 13 | export const Ref = () => ({ 14 | Component: RefExample, 15 | }); 16 | 17 | export const Events = () => ({ 18 | Component: EventsExample, 19 | }); 20 | -------------------------------------------------------------------------------- /stories/doughnut.stories.ts: -------------------------------------------------------------------------------- 1 | import { Doughnut } from '../src'; 2 | import DefaultExample from '../sandboxes/doughnut/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'Doughnut', 6 | component: Doughnut, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /stories/line.stories.ts: -------------------------------------------------------------------------------- 1 | import { Line } from '../src'; 2 | import DefaultExample from '../sandboxes/line/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'Line', 6 | component: Line, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /stories/pie.stories.ts: -------------------------------------------------------------------------------- 1 | import { Pie } from '../src'; 2 | import DefaultExample from '../sandboxes/pie/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'Pie', 6 | component: Pie, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /stories/polar.stories.ts: -------------------------------------------------------------------------------- 1 | import { PolarArea } from '../src'; 2 | import DefaultExample from '../sandboxes/polar/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'PolarArea', 6 | component: PolarArea, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /stories/radar.stories.ts: -------------------------------------------------------------------------------- 1 | import { Radar } from '../src'; 2 | import DefaultExample from '../sandboxes/radar/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'Radar', 6 | component: Radar, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /stories/scatter.stories.ts: -------------------------------------------------------------------------------- 1 | import { Scatter } from '../src'; 2 | import DefaultExample from '../sandboxes/scatter/components/Chart.svelte'; 3 | 4 | export default { 5 | title: 'Scatter', 6 | component: Scatter, 7 | parameters: { 8 | layout: 'centered', 9 | }, 10 | }; 11 | 12 | export const Default = () => ({ 13 | Component: DefaultExample, 14 | }); 15 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 2 | 3 | export default { 4 | preprocess: vitePreprocess(), 5 | }; 6 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/Bar.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { Bar } from '../src/index.js'; 6 | import { data } from '../sandboxes/bar/components/data.js'; 7 | 8 | const options = { 9 | responsive: true, 10 | }; 11 | 12 | describe('Bar Chart', () => { 13 | it('should render a canvas', () => { 14 | const { container } = render(Bar); 15 | const canvas = container.querySelector('canvas'); 16 | 17 | expect(canvas).not.toBeNull(); 18 | }); 19 | 20 | it('should pass data prop', () => { 21 | const component = render(Bar, { props: { data } }); 22 | 23 | expect(() => component).not.toThrow(); 24 | }); 25 | 26 | it('should pass options prop', () => { 27 | const component = render(Bar, { props: { options } }); 28 | 29 | expect(() => component).not.toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/Bubble.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { Bubble } from '../src/index.js'; 6 | import { data } from '../sandboxes/bubble/components/data.js'; 7 | 8 | const options = { 9 | responsive: true, 10 | }; 11 | 12 | describe('Bubble Chart', () => { 13 | it('should render a canvas', () => { 14 | const { container } = render(Bubble); 15 | const canvas = container.querySelector('canvas'); 16 | 17 | expect(canvas).not.toBeNull(); 18 | }); 19 | 20 | it('should pass data prop', () => { 21 | const component = render(Bubble, { props: { data } }); 22 | 23 | expect(() => component).not.toThrow(); 24 | }); 25 | 26 | it('should pass options prop', () => { 27 | const component = render(Bubble, { props: { options } }); 28 | 29 | expect(() => component).not.toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/Doughnut.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { Doughnut } from '../src/index.js'; 6 | import { data } from '../sandboxes/doughnut/components/data.js'; 7 | 8 | const options = { 9 | responsive: true, 10 | }; 11 | 12 | describe('Doughnut Chart', () => { 13 | it('should render a canvas', () => { 14 | const { container } = render(Doughnut); 15 | const canvas = container.querySelector('canvas'); 16 | 17 | expect(canvas).not.toBeNull(); 18 | }); 19 | 20 | it('should pass data prop', () => { 21 | const component = render(Doughnut, { props: { data } }); 22 | 23 | expect(() => component).not.toThrow(); 24 | }); 25 | 26 | it('should pass options prop', () => { 27 | const component = render(Doughnut, { props: { options } }); 28 | 29 | expect(() => component).not.toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/Line.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { Line } from '../src/index.js'; 6 | import { data } from '../sandboxes/line/components/data.js'; 7 | 8 | const options = { 9 | responsive: true, 10 | }; 11 | 12 | describe('Line Chart', () => { 13 | it('should render a canvas', () => { 14 | const { container } = render(Line); 15 | const canvas = container.querySelector('canvas'); 16 | 17 | expect(canvas).not.toBeNull(); 18 | }); 19 | 20 | it('should pass data prop', () => { 21 | const component = render(Line, { props: { data } }); 22 | 23 | expect(() => component).not.toThrow(); 24 | }); 25 | 26 | it('should pass options prop', () => { 27 | const component = render(Line, { props: { options } }); 28 | 29 | expect(() => component).not.toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/Pie.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { Pie } from '../src/index.js'; 6 | import { data } from '../sandboxes/pie/components/data.js'; 7 | 8 | const options = { 9 | responsive: true, 10 | }; 11 | 12 | describe('Pie Chart', () => { 13 | it('should render a canvas', () => { 14 | const { container } = render(Pie); 15 | const canvas = container.querySelector('canvas'); 16 | 17 | expect(canvas).not.toBeNull(); 18 | }); 19 | 20 | it('should pass data prop', () => { 21 | const component = render(Pie, { props: { data } }); 22 | 23 | expect(() => component).not.toThrow(); 24 | }); 25 | 26 | it('should pass options prop', () => { 27 | const component = render(Pie, { props: { options } }); 28 | 29 | expect(() => component).not.toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/PolarArea.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { PolarArea } from '../src/index.js'; 6 | import { data } from '../sandboxes/polar/components/data.js'; 7 | 8 | const options = { 9 | responsive: true, 10 | }; 11 | 12 | describe('Polar Chart', () => { 13 | it('should render a canvas', () => { 14 | const { container } = render(PolarArea); 15 | const canvas = container.querySelector('canvas'); 16 | 17 | expect(canvas).not.toBeNull(); 18 | }); 19 | 20 | it('should pass data prop', () => { 21 | const component = render(PolarArea, { props: { data } }); 22 | 23 | expect(() => component).not.toThrow(); 24 | }); 25 | 26 | it('should pass options prop', () => { 27 | const component = render(PolarArea, { props: { options } }); 28 | 29 | expect(() => component).not.toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/Radar.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { Radar } from '../src/index.js'; 6 | import { data } from '../sandboxes/radar/components/data.js'; 7 | 8 | const options = { 9 | responsive: true, 10 | }; 11 | 12 | describe('Radar Chart', () => { 13 | it('should render a canvas', () => { 14 | const { container } = render(Radar); 15 | const canvas = container.querySelector('canvas'); 16 | 17 | expect(canvas).not.toBeNull(); 18 | }); 19 | 20 | it('should pass data prop', () => { 21 | const component = render(Radar, { props: { data } }); 22 | 23 | expect(() => component).not.toThrow(); 24 | }); 25 | 26 | it('should pass options prop', () => { 27 | const component = render(Radar, { props: { options } }); 28 | 29 | expect(() => component).not.toThrow(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/Scatter.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { render } from '@testing-library/svelte'; 3 | 4 | import 'chart.js/auto'; 5 | import { Scatter } from '../src/index.js'; 6 | import { data } from '../sandboxes/scatter/components/data.js'; 7 | 8 | const options = { 9 | title: { 10 | display: true, 11 | text: 'Scatter Chart - Logarithmic X-Axis', 12 | }, 13 | }; 14 | 15 | describe('Scatter Chart', () => { 16 | it('should render a canvas', () => { 17 | const { container } = render(Scatter); 18 | const canvas = container.querySelector('canvas'); 19 | 20 | expect(canvas).not.toBeNull(); 21 | }); 22 | 23 | it('should pass data prop', () => { 24 | const component = render(Scatter, { props: { data } }); 25 | 26 | expect(() => component).not.toThrow(); 27 | }); 28 | 29 | it('should pass options prop', () => { 30 | const component = render(Scatter, { props: { options } }); 31 | 32 | expect(() => component).not.toThrow(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | import { afterEach, vi } from 'vitest'; 2 | import { cleanup } from '@testing-library/svelte'; 3 | 4 | import '@testing-library/jest-dom/vitest'; 5 | import 'vitest-canvas-mock'; 6 | 7 | afterEach(cleanup); 8 | 9 | window.ResizeObserver = 10 | window.ResizeObserver || 11 | vi.fn().mockImplementation(() => ({ 12 | disconnect: vi.fn(), 13 | observe: vi.fn(), 14 | unobserve: vi.fn(), 15 | })); 16 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": [ 4 | "./", 5 | "../sandboxes" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "module": "esnext", 5 | "moduleResolution": "NodeNext", 6 | "resolveJsonModule": true, 7 | "types": [ 8 | "svelte" 9 | ], 10 | "target": "ES2020", 11 | "lib": ["ES2021", "DOM"], 12 | /** 13 | Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript 14 | to enforce using `import type` instead of `import` for Types. 15 | */ 16 | "importsNotUsedAsValues": "error", 17 | /** 18 | TypeScript doesn't know about import usages in the template because it only sees the 19 | script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher. 20 | */ 21 | "preserveValueImports": true, 22 | "isolatedModules": true, 23 | /** 24 | To have warnings/errors of the Svelte compiler at the correct position, 25 | enable source maps by default. 26 | */ 27 | "sourceMap": true, 28 | "strict": false, 29 | "esModuleInterop": true, 30 | "forceConsistentCasingInFileNames": true, 31 | /* Emit */ 32 | "declaration": true, 33 | "declarationMap": true, 34 | "outDir": "dist", 35 | /* Completeness */ 36 | "skipLibCheck": true 37 | }, 38 | "include": [ 39 | "src" 40 | ], 41 | "exclude": [ 42 | "dist" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | export default defineConfig({ 5 | plugins: [svelte()], 6 | test: { 7 | dir: './', 8 | environment: 'jsdom', 9 | include: ['./test/*.spec.ts'], 10 | setupFiles: ['./test/setup.js'], 11 | coverage: { 12 | include: ['src'], 13 | reporters: ['lcovonly', 'text'], 14 | }, 15 | }, 16 | }); 17 | --------------------------------------------------------------------------------