├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ └── browser-test.yml ├── .gitignore ├── .npmrc ├── .prettierrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── debug ├── nuxt3 │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── app.vue │ ├── nuxt.config.ts │ ├── package.json │ ├── plugins │ │ └── chartjs.client.ts │ ├── tsconfig.json │ └── yarn.lock ├── vite │ ├── .gitignore │ ├── .vscode │ │ └── extensions.json │ ├── README.md │ ├── index.html │ ├── package.json │ ├── pnpm-lock.yaml │ ├── public │ │ └── favicon.ico │ ├── src │ │ ├── App.vue │ │ ├── cases │ │ │ └── PushData.vue │ │ ├── env.d.ts │ │ └── main.ts │ ├── tsconfig.json │ └── vite.config.ts └── vue-cli │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package.json │ ├── pnpm-lock.yaml │ ├── public │ ├── favicon.ico │ └── index.html │ ├── src │ ├── App.vue │ ├── main.ts │ ├── mixed.d.ts │ └── shims-vue.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── docs ├── .vuepress │ ├── config.ts │ ├── public │ │ ├── favicon.ico │ │ └── images │ │ │ ├── logo.png │ │ │ └── logo.svg │ └── styles │ │ ├── index.scss │ │ └── palette.scss ├── README.md ├── components │ ├── README.md │ └── hooks │ │ ├── README.md │ │ └── example.md ├── guide │ ├── README.md │ ├── configuration │ │ ├── README.md │ │ └── plugins.md │ ├── examples.md │ ├── examples │ │ ├── nuxt2.md │ │ ├── vue2-class.md │ │ ├── vue2-composition.md │ │ └── vue3.md │ └── usage │ │ ├── README.md │ │ ├── actions.md │ │ ├── chart-instance.md │ │ ├── dynamic-data.md │ │ ├── manual-update.md │ │ └── typescript.md └── package.json ├── media └── logo.svg ├── package.json ├── pnpm-lock.yaml ├── src ├── core │ ├── component.builder.ts │ ├── component.types.ts │ └── index.ts ├── exports │ ├── component.exports.ts │ ├── hooks.exports.ts │ └── index.ts ├── hooks │ ├── hooks.builder.ts │ ├── hooks.types.ts │ └── index.ts ├── index.ts ├── misc │ ├── index.ts │ └── vue.types.ts └── utils │ ├── format.utils.ts │ ├── index.ts │ └── types.utils.ts ├── tests ├── setup.d.ts ├── setup.ts ├── unit │ ├── components │ │ └── BarChart.spec.ts │ └── vue3.spec.ts └── utils │ ├── index.ts │ ├── misc.utils.ts │ └── setup.utils.ts ├── tsconfig.build.json ├── tsconfig.json ├── tsup.config.ts └── vite.config.ts /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41E Bug report" 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Describe the bug 11 | *A clear and concise description of what the bug is.* 12 | 13 | # Remember, `vue-chart-3` is only an *adapter* to use `chart.js` with Vue easily. So any `chart.js` related issue or question will be dismissed 14 | 15 | ## To Reproduce 16 | 17 | *Put a reproduction link here based on this templates* 18 | 19 | - [Template for Vue 3](https://codesandbox.io/s/demo-vue-chart-3-ugynm) 20 | - [Template for Vue 2](https://codesandbox.io/s/vue-chart-3-vue-2-composition-api-mw54f) 21 | - [Template for Nuxt 2](https://codesandbox.io/s/vue-chart-3-nuxt-2-mrtej) 22 | 23 | ## Version of `vue-chart-3` 24 | *ex: v3.0.2* 25 | 26 | ## Version of Vue 27 | 28 | - [ ] Vue 3 29 | - [ ] Vue 2 30 | - [ ] Nuxt 2 31 | - [ ] Nuxt 3 32 | -------------------------------------------------------------------------------- /.github/workflows/browser-test.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [14.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - run: yarn 21 | - run: yarn test 22 | env: 23 | CI: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | .temp 18 | .cache 19 | .DS_STORE 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | *.lcov 27 | 28 | # nyc test coverage 29 | .nyc_output 30 | 31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 32 | .grunt 33 | 34 | # Bower dependency directory (https://bower.io/) 35 | bower_components 36 | 37 | # node-waf configuration 38 | .lock-wscript 39 | 40 | # Compiled binary addons (https://nodejs.org/api/addons.html) 41 | build/Release 42 | 43 | # Dependency directories 44 | node_modules/ 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | types/ 50 | 51 | # TypeScript cache 52 | *.tsbuildinfo 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variables file 76 | .env 77 | .env.test 78 | 79 | # parcel-bundler cache (https://parceljs.org/) 80 | .cache 81 | 82 | # Next.js build output 83 | .next 84 | 85 | # Nuxt.js build / generate output 86 | .nuxt 87 | dist 88 | 89 | # Gatsby files 90 | .cache/ 91 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 92 | # https://nextjs.org/blog/next-9-1#public-directory-support 93 | # public 94 | 95 | # vuepress build output 96 | .vuepress/dist 97 | 98 | # Serverless directories 99 | .serverless/ 100 | 101 | # FuseBox cache 102 | .fusebox/ 103 | 104 | # DynamoDB Local files 105 | .dynamodb/ 106 | 107 | # TernJS port file 108 | .tern-port 109 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist = true -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "trailingComma": "es5", 5 | "singleQuote": true, 6 | "semi": true, 7 | "bracketSpacing": true 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib" 3 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # 3.1.3 (2022-03-08) 7 | 8 | - Fixed array mutation call stack loop #58 9 | - Fixed animations for array mutations 10 | 11 | # 3.1.2 (2022-02-23) 12 | 13 | - Fixed pascalCase 14 | 15 | # 3.1.1 (2022-02-22) 16 | 17 | - Fixed @vue/runtime-[core|dom] peer deps 18 | - Refacto unit tests 19 | 20 | # 3.1.0 (2022-02-15) 21 | 22 | - Refactored the project to add esm and cjs builds 23 | - Compatible with Vite.js and Nuxt 3 24 | - Changed Jest to Vitest ⚡️ 25 | - Fixed docs 26 | - Added useful JSdocs 27 | - more 28 | 29 | # 3.0.9 (2022-01-21) 30 | 31 | # 3.0.0 and 2.0.0 (2021-11-23) 32 | 33 | - Breaking changes and new versions numbers 34 | 35 | In previous versions, `vue-demi` was used. It worked really well, but as the project advanced, they were a lot of problems with vue-related typescript definitions, tests and conflict between dependencies. 36 | 37 | This new system will keep `vue-chart-3` working for both Vue 2 & 3 with designated versions (`2.x` and `3.x` respectively), but each one designed for their specific Vue version. 38 | 39 | The usage of components of hooks is unchanged for both versions. 40 | 41 | Code wise, there is not big breaking changes. But the Vue 3 version will have improved type checking for components template (with Volar extension). 42 | 43 | - New docs using vuepress next! 44 | 45 | # 0.5.10 (2021-10-27) 46 | 47 | - Fixed types for Vue 3 imports 48 | 49 | # 0.5.10 (2021-10-25) 50 | 51 | - Fix `postinstall` bugs with npm update 52 | 53 | # 0.5.9 (2021-10-25) 54 | 55 | - Fix `Plugin` types in hooks 56 | 57 | # 0.4.7 (2021-07-18) 58 | 59 | - `chartInstance` is now accessible by reference to the component! 60 | 61 | # 0.4.5 (2021-07-18) 62 | 63 | - Fixed call stack loop when using reactive options using data or ref 64 | - Fixed bundle size thanks to @DRoet 65 | 66 | # 0.4.1 (2021-07-16) 67 | 68 | - Fixed component names taking chartId instead of chartType 69 | 70 | # 0.4.0 (2021-07-16) 71 | 72 | # Breaking changes 73 | 74 | - Renamed `data` prop to `chartData` due to type merging issues 75 | 76 | # Features 77 | 78 | - All components are now correctly typed if using Volar on VSCode 79 | - Added `ExtractComponentData` utility type 80 | - Added `ExtractComponentProps` utility type 81 | - Reactive `options` 82 | 83 | # 0.4.0-alpha.1 (2021-07-15) 84 | 85 | **Note:** Version bump only for package vue-chart-3 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Victor Garcia 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 | ## I'm joining [vue-chartjs](https://github.com/apertureless/vue-chartjs) as a core maintainer so this package will be kept just for those who already use it. I'm encouraging new users to use `vue-chartjs` instead 2 | 3 | # 📊 Chart.js 3 for Vue 2 and Vue 3 4 | 5 |

6 | 7 | sgts logo 8 | 9 |

10 | 11 |
12 | 13 | [![npm version][npm-version-src]][npm-version-href] 14 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 15 | [![npm downloads][npm-total-downloads-src]][npm-downloads-href] 16 | 17 | 18 |
19 | 20 | [npm-version-src]: https://img.shields.io/npm/v/vue-chart-3.svg 21 | [npm-version-href]: https://www.npmjs.com/package/vue-chart-3 22 | [npm-downloads-src]: https://img.shields.io/npm/dm/vue-chart-3.svg 23 | [npm-total-downloads-src]: https://img.shields.io/npm/dt/vue-chart-3.svg 24 | [npm-downloads-href]: https://www.npmjs.com/package/vue-chart-3 25 | 26 | This package is a rewrite of [vue-chartjs](https://github.com/apertureless/vue-chartjs) for Chart.js 3, but written in Typescript with Vue 3 composition api in mind. 27 | 28 | - `Vite.js` and `Nuxt 3` compatible 💯. 29 | 30 | # [Documentation](https://vue-chart-3.netlify.app/) 31 | 32 | [Full documentation](https://vue-chart-3.netlify.app/) 33 | 34 | # Installation 35 | 36 | ## For Vue 3 37 | 38 | ```bash 39 | npm i vue-chart-3 chart.js 40 | #or 41 | yarn add vue-chart-3 chart.js 42 | #or 43 | pnpm i vue-chart-3 chart.js 44 | ``` 45 | 46 | ## For Vue 2 47 | 48 | ```bash 49 | npm i vue-chart-3@legacy chart.js 50 | #or 51 | yarn add vue-chart-3@legacy chart.js 52 | #or 53 | pnpm i vue-chart-3@legacy chart.js 54 | ``` 55 | 56 | # Important notes 57 | 58 | ## Using with Vue 3 or Vue 2 59 | 60 | This package works with version 2.x and 3.x of Vue. 61 | 62 | - Vue 3 works out-of-the-box 63 | - Vue 2 requires `@vue/composition-api` package to also be installed and registered, to provide Vue 3's [Composition API](https://v3.vuejs.org/guide/composition-api-introduction.html) features like `ref, defineComponent, computed, reactive`. 64 | 65 | # Demos 66 | 67 | - Vue 3: [CodeSandbox demo Vue 3](https://codesandbox.io/s/demo-vue-chart-3-ugynm?file=/src/App.vue) 68 | - Vue 2 + composition API: [CodeSandbox demo Vue 2 + composition](https://codesandbox.io/s/vue-chart-3-vue-2-mw54f?file=/src/App.vue) 69 | - Vue 2 + Typescript + class API [CodeSandox demo Vue 2 + class](https://codesandbox.io/s/vue-chart-3-vue-2-class-api-f7gv1?file=/src/App.vue) 70 | - Nuxt 2 + SSR [CodeSandbox demo Nuxt 2 + SSR](https://codesandbox.io/s/vue-chart-3-nuxt-2-mrtej?file=/pages/index.vue) 71 | -------------------------------------------------------------------------------- /debug/nuxt3/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .nuxt 4 | nuxt.d.ts 5 | .output 6 | .env -------------------------------------------------------------------------------- /debug/nuxt3/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist = true -------------------------------------------------------------------------------- /debug/nuxt3/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | We recommend to look at the [documentation](https://v3.nuxtjs.org). 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies 8 | 9 | ```bash 10 | yarn install 11 | ``` 12 | 13 | ## Development 14 | 15 | Start the development server on http://localhost:3000 16 | 17 | ```bash 18 | yarn dev 19 | ``` 20 | 21 | ## Production 22 | 23 | Build the application for production: 24 | 25 | ```bash 26 | yarn build 27 | ``` 28 | 29 | Checkout the [deployment documentation](https://v3.nuxtjs.org/docs/deployment). -------------------------------------------------------------------------------- /debug/nuxt3/app.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 59 | 60 | 70 | -------------------------------------------------------------------------------- /debug/nuxt3/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtConfig } from 'nuxt3'; 2 | 3 | // https://v3.nuxtjs.org/docs/directory-structure/nuxt.config 4 | export default defineNuxtConfig({}); 5 | -------------------------------------------------------------------------------- /debug/nuxt3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "nuxi dev", 5 | "build": "nuxi build", 6 | "start": "node .output/server/index.mjs" 7 | }, 8 | "devDependencies": { 9 | "nuxt3": "latest", 10 | "unenv": "^0.4.3" 11 | }, 12 | "dependencies": { 13 | "@types/lodash-es": "^4.17.5", 14 | "chart.js": "^3.7.0", 15 | "lodash-es": "^4.17.21", 16 | "vue-chart-3": "^3.1.0-rc.8" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /debug/nuxt3/plugins/chartjs.client.ts: -------------------------------------------------------------------------------- 1 | import { defineNuxtPlugin } from '#app'; 2 | 3 | import * as ChartJs from 'chart.js'; 4 | const { Chart, registerables } = ChartJs; 5 | 6 | export default defineNuxtPlugin(() => { 7 | Chart.register(...registerables); 8 | }); 9 | -------------------------------------------------------------------------------- /debug/nuxt3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /debug/vite/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | -------------------------------------------------------------------------------- /debug/vite/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /debug/vite/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Typescript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 ` 12 | 13 | 14 | -------------------------------------------------------------------------------- /debug/vite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vue-tsc --noEmit && vite build", 7 | "preview": "vite preview" 8 | }, 9 | "dependencies": { 10 | "@types/lodash-es": "^4.17.5", 11 | "chart.js": "^3.7.0", 12 | "lodash-es": "^4.17.21", 13 | "vue": "^3.2.31", 14 | "vue-chart-3": "^3.1.3" 15 | }, 16 | "devDependencies": { 17 | "@vitejs/plugin-vue": "^2.0.0", 18 | "typescript": "^4.4.4", 19 | "vite": "^2.7.2", 20 | "vue-tsc": "^0.29.8" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /debug/vite/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.3 2 | 3 | specifiers: 4 | '@types/lodash-es': ^4.17.5 5 | '@vitejs/plugin-vue': ^2.0.0 6 | chart.js: ^3.7.0 7 | lodash-es: ^4.17.21 8 | typescript: ^4.4.4 9 | vite: ^2.7.2 10 | vue: ^3.2.31 11 | vue-chart-3: ^3.1.3 12 | vue-tsc: ^0.29.8 13 | 14 | dependencies: 15 | '@types/lodash-es': 4.17.5 16 | chart.js: 3.7.0 17 | lodash-es: 4.17.21 18 | vue: 3.2.31 19 | vue-chart-3: 3.1.3_chart.js@3.7.0+vue@3.2.31 20 | 21 | devDependencies: 22 | '@vitejs/plugin-vue': 2.1.0_vite@2.7.13+vue@3.2.31 23 | typescript: 4.5.5 24 | vite: 2.7.13 25 | vue-tsc: 0.29.8_typescript@4.5.5 26 | 27 | packages: 28 | 29 | /@babel/helper-validator-identifier/7.16.7: 30 | resolution: {integrity: sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==} 31 | engines: {node: '>=6.9.0'} 32 | dev: true 33 | 34 | /@babel/parser/7.17.0: 35 | resolution: {integrity: sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw==} 36 | engines: {node: '>=6.0.0'} 37 | hasBin: true 38 | 39 | /@babel/types/7.17.0: 40 | resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} 41 | engines: {node: '>=6.9.0'} 42 | dependencies: 43 | '@babel/helper-validator-identifier': 7.16.7 44 | to-fast-properties: 2.0.0 45 | dev: true 46 | 47 | /@emmetio/abbreviation/2.2.2: 48 | resolution: {integrity: sha512-TtE/dBnkTCct8+LntkqVrwqQao6EnPAs1YN3cUgxOxTaBlesBCY37ROUAVZrRlG64GNnVShdl/b70RfAI3w5lw==} 49 | dependencies: 50 | '@emmetio/scanner': 1.0.0 51 | dev: true 52 | 53 | /@emmetio/css-abbreviation/2.1.4: 54 | resolution: {integrity: sha512-qk9L60Y+uRtM5CPbB0y+QNl/1XKE09mSO+AhhSauIfr2YOx/ta3NJw2d8RtCFxgzHeRqFRr8jgyzThbu+MZ4Uw==} 55 | dependencies: 56 | '@emmetio/scanner': 1.0.0 57 | dev: true 58 | 59 | /@emmetio/scanner/1.0.0: 60 | resolution: {integrity: sha512-8HqW8EVqjnCmWXVpqAOZf+EGESdkR27odcMMMGefgKXtar00SoYNSryGv//TELI4T3QFsECo78p+0lmalk/CFA==} 61 | dev: true 62 | 63 | /@types/lodash-es/4.17.5: 64 | resolution: {integrity: sha512-SHBoI8/0aoMQWAgUHMQ599VM6ZiSKg8sh/0cFqqlQQMyY9uEplc0ULU5yQNzcvdR4ZKa0ey8+vFmahuRbOCT1A==} 65 | dependencies: 66 | '@types/lodash': 4.14.178 67 | dev: false 68 | 69 | /@types/lodash/4.14.178: 70 | resolution: {integrity: sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==} 71 | dev: false 72 | 73 | /@vitejs/plugin-vue/2.1.0_vite@2.7.13+vue@3.2.31: 74 | resolution: {integrity: sha512-AZ78WxvFMYd8JmM/GBV6a6SGGTU0GgN/0/4T+FnMMsLzFEzTeAUwuraapy50ifHZsC+G5SvWs86bvaCPTneFlA==} 75 | engines: {node: '>=12.0.0'} 76 | peerDependencies: 77 | vite: ^2.5.10 78 | vue: ^3.2.25 79 | dependencies: 80 | vite: 2.7.13 81 | vue: 3.2.31 82 | dev: true 83 | 84 | /@volar/code-gen/0.29.8: 85 | resolution: {integrity: sha512-eohLLUqPChHRPDFT5gXn4V6pr/CeTri7Ou5GI26lUvBRRAbP8p+oYfQRcbMPGeKmVkYjfVj0chsxQGx6T8PQ4Q==} 86 | dependencies: 87 | '@volar/shared': 0.29.8 88 | '@volar/source-map': 0.29.8 89 | dev: true 90 | 91 | /@volar/html2pug/0.29.8: 92 | resolution: {integrity: sha512-bhSNXg8A2aD3w0B+CwmHjqCAaKtj5rORbE5C/q/UdGqptJbC6STCmi30KuRTdfPhR++Xb18Hauf3s/WCmtNAPA==} 93 | dependencies: 94 | domelementtype: 2.2.0 95 | domhandler: 4.3.0 96 | htmlparser2: 7.2.0 97 | pug: 3.0.2 98 | dev: true 99 | 100 | /@volar/shared/0.29.8: 101 | resolution: {integrity: sha512-Y1NN6irkIukD+T0wf4p/dHWYL90sacN2e2lYoDXxRlvoYxwANnHgw0J0Rcp+yw58ElWRScdG7/YntEIuZWeJsw==} 102 | dependencies: 103 | upath: 2.0.1 104 | vscode-jsonrpc: 8.0.0-next.6 105 | vscode-uri: 3.0.3 106 | dev: true 107 | 108 | /@volar/source-map/0.29.8: 109 | resolution: {integrity: sha512-7w+UoYtnc6UQu30CgMVvx0YN4dzDgP4TIsSmUaW62AGmxU9Lxwp3Kkn/4N8efi91z8ma5Z78v/HddyJPwAC3LA==} 110 | dependencies: 111 | '@volar/shared': 0.29.8 112 | dev: true 113 | 114 | /@volar/transforms/0.29.8: 115 | resolution: {integrity: sha512-o2hRa8CoDwYTO1Mu5KA47+1elUnYUjDaVhCvbyKlRfd8qpHea2llotArq7B6OORSL2M9DVs1IRJ5NGURBFeZ3Q==} 116 | dependencies: 117 | '@volar/shared': 0.29.8 118 | vscode-languageserver: 8.0.0-next.8 119 | dev: true 120 | 121 | /@volar/vue-code-gen/0.29.8: 122 | resolution: {integrity: sha512-E1e7P2oktNC/DzgDBditfla4s8+HlUlluZ+BtcLvEdbkl3QEjujkB0x1wxguWzXmpWgLIDPtrS3Jzll5cCOkTg==} 123 | dependencies: 124 | '@volar/code-gen': 0.29.8 125 | '@volar/shared': 0.29.8 126 | '@volar/source-map': 0.29.8 127 | '@vue/compiler-core': 3.2.31 128 | '@vue/compiler-dom': 3.2.31 129 | '@vue/shared': 3.2.31 130 | upath: 2.0.1 131 | dev: true 132 | 133 | /@vscode/emmet-helper/2.8.3: 134 | resolution: {integrity: sha512-dkTSL+BaBBS8gFgPm/GMOU+XfxaMyI+Fl1IUYxEi8Iv24RfHf9/q2eCpV2hs7sncLcoKWEbMYe5gv4Ppmp2Oxw==} 135 | dependencies: 136 | emmet: 2.3.5 137 | jsonc-parser: 2.3.1 138 | vscode-languageserver-textdocument: 1.0.4 139 | vscode-languageserver-types: 3.16.0 140 | vscode-nls: 5.0.0 141 | vscode-uri: 2.1.2 142 | dev: true 143 | 144 | /@vue/compiler-core/3.2.31: 145 | resolution: {integrity: sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==} 146 | dependencies: 147 | '@babel/parser': 7.17.0 148 | '@vue/shared': 3.2.31 149 | estree-walker: 2.0.2 150 | source-map: 0.6.1 151 | 152 | /@vue/compiler-dom/3.2.31: 153 | resolution: {integrity: sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==} 154 | dependencies: 155 | '@vue/compiler-core': 3.2.31 156 | '@vue/shared': 3.2.31 157 | 158 | /@vue/compiler-sfc/3.2.31: 159 | resolution: {integrity: sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==} 160 | dependencies: 161 | '@babel/parser': 7.17.0 162 | '@vue/compiler-core': 3.2.31 163 | '@vue/compiler-dom': 3.2.31 164 | '@vue/compiler-ssr': 3.2.31 165 | '@vue/reactivity-transform': 3.2.31 166 | '@vue/shared': 3.2.31 167 | estree-walker: 2.0.2 168 | magic-string: 0.25.7 169 | postcss: 8.4.6 170 | source-map: 0.6.1 171 | dev: false 172 | 173 | /@vue/compiler-ssr/3.2.31: 174 | resolution: {integrity: sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==} 175 | dependencies: 176 | '@vue/compiler-dom': 3.2.31 177 | '@vue/shared': 3.2.31 178 | dev: false 179 | 180 | /@vue/reactivity-transform/3.2.31: 181 | resolution: {integrity: sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==} 182 | dependencies: 183 | '@babel/parser': 7.17.0 184 | '@vue/compiler-core': 3.2.31 185 | '@vue/shared': 3.2.31 186 | estree-walker: 2.0.2 187 | magic-string: 0.25.7 188 | dev: false 189 | 190 | /@vue/reactivity/3.2.31: 191 | resolution: {integrity: sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==} 192 | dependencies: 193 | '@vue/shared': 3.2.31 194 | 195 | /@vue/runtime-core/3.2.31: 196 | resolution: {integrity: sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==} 197 | dependencies: 198 | '@vue/reactivity': 3.2.31 199 | '@vue/shared': 3.2.31 200 | dev: false 201 | 202 | /@vue/runtime-dom/3.2.31: 203 | resolution: {integrity: sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==} 204 | dependencies: 205 | '@vue/runtime-core': 3.2.31 206 | '@vue/shared': 3.2.31 207 | csstype: 2.6.19 208 | dev: false 209 | 210 | /@vue/server-renderer/3.2.31_vue@3.2.31: 211 | resolution: {integrity: sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==} 212 | peerDependencies: 213 | vue: 3.2.31 214 | dependencies: 215 | '@vue/compiler-ssr': 3.2.31 216 | '@vue/shared': 3.2.31 217 | vue: 3.2.31 218 | dev: false 219 | 220 | /@vue/shared/3.2.31: 221 | resolution: {integrity: sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==} 222 | 223 | /acorn/7.4.1: 224 | resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} 225 | engines: {node: '>=0.4.0'} 226 | hasBin: true 227 | dev: true 228 | 229 | /asap/2.0.6: 230 | resolution: {integrity: sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=} 231 | dev: true 232 | 233 | /assert-never/1.2.1: 234 | resolution: {integrity: sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==} 235 | dev: true 236 | 237 | /babel-walk/3.0.0-canary-5: 238 | resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==} 239 | engines: {node: '>= 10.0.0'} 240 | dependencies: 241 | '@babel/types': 7.17.0 242 | dev: true 243 | 244 | /call-bind/1.0.2: 245 | resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} 246 | dependencies: 247 | function-bind: 1.1.1 248 | get-intrinsic: 1.1.1 249 | dev: true 250 | 251 | /character-parser/2.2.0: 252 | resolution: {integrity: sha1-x84o821LzZdE5f/CxfzeHHMmH8A=} 253 | dependencies: 254 | is-regex: 1.1.4 255 | dev: true 256 | 257 | /chart.js/3.7.0: 258 | resolution: {integrity: sha512-31gVuqqKp3lDIFmzpKIrBeum4OpZsQjSIAqlOpgjosHDJZlULtvwLEZKtEhIAZc7JMPaHlYMys40Qy9Mf+1AAg==} 259 | dev: false 260 | 261 | /constantinople/4.0.1: 262 | resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==} 263 | dependencies: 264 | '@babel/parser': 7.17.0 265 | '@babel/types': 7.17.0 266 | dev: true 267 | 268 | /csstype/2.6.19: 269 | resolution: {integrity: sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==} 270 | dev: false 271 | 272 | /csstype/3.0.11: 273 | resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} 274 | dev: false 275 | 276 | /doctypes/1.1.0: 277 | resolution: {integrity: sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=} 278 | dev: true 279 | 280 | /dom-serializer/1.3.2: 281 | resolution: {integrity: sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==} 282 | dependencies: 283 | domelementtype: 2.2.0 284 | domhandler: 4.3.0 285 | entities: 2.2.0 286 | dev: true 287 | 288 | /domelementtype/2.2.0: 289 | resolution: {integrity: sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==} 290 | dev: true 291 | 292 | /domhandler/4.3.0: 293 | resolution: {integrity: sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==} 294 | engines: {node: '>= 4'} 295 | dependencies: 296 | domelementtype: 2.2.0 297 | dev: true 298 | 299 | /domutils/2.8.0: 300 | resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} 301 | dependencies: 302 | dom-serializer: 1.3.2 303 | domelementtype: 2.2.0 304 | domhandler: 4.3.0 305 | dev: true 306 | 307 | /emmet/2.3.5: 308 | resolution: {integrity: sha512-LcWfTamJnXIdMfLvJEC5Ld3hY5/KHXgv1L1bp6I7eEvB0ZhacHZ1kX0BYovJ8FroEsreLcq7n7kZhRMsf6jkXQ==} 309 | dependencies: 310 | '@emmetio/abbreviation': 2.2.2 311 | '@emmetio/css-abbreviation': 2.1.4 312 | dev: true 313 | 314 | /entities/2.2.0: 315 | resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} 316 | dev: true 317 | 318 | /entities/3.0.1: 319 | resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} 320 | engines: {node: '>=0.12'} 321 | dev: true 322 | 323 | /esbuild-android-arm64/0.13.15: 324 | resolution: {integrity: sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==} 325 | cpu: [arm64] 326 | os: [android] 327 | requiresBuild: true 328 | dev: true 329 | optional: true 330 | 331 | /esbuild-darwin-64/0.13.15: 332 | resolution: {integrity: sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==} 333 | cpu: [x64] 334 | os: [darwin] 335 | requiresBuild: true 336 | dev: true 337 | optional: true 338 | 339 | /esbuild-darwin-arm64/0.13.15: 340 | resolution: {integrity: sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==} 341 | cpu: [arm64] 342 | os: [darwin] 343 | requiresBuild: true 344 | dev: true 345 | optional: true 346 | 347 | /esbuild-freebsd-64/0.13.15: 348 | resolution: {integrity: sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==} 349 | cpu: [x64] 350 | os: [freebsd] 351 | requiresBuild: true 352 | dev: true 353 | optional: true 354 | 355 | /esbuild-freebsd-arm64/0.13.15: 356 | resolution: {integrity: sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==} 357 | cpu: [arm64] 358 | os: [freebsd] 359 | requiresBuild: true 360 | dev: true 361 | optional: true 362 | 363 | /esbuild-linux-32/0.13.15: 364 | resolution: {integrity: sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==} 365 | cpu: [ia32] 366 | os: [linux] 367 | requiresBuild: true 368 | dev: true 369 | optional: true 370 | 371 | /esbuild-linux-64/0.13.15: 372 | resolution: {integrity: sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==} 373 | cpu: [x64] 374 | os: [linux] 375 | requiresBuild: true 376 | dev: true 377 | optional: true 378 | 379 | /esbuild-linux-arm/0.13.15: 380 | resolution: {integrity: sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==} 381 | cpu: [arm] 382 | os: [linux] 383 | requiresBuild: true 384 | dev: true 385 | optional: true 386 | 387 | /esbuild-linux-arm64/0.13.15: 388 | resolution: {integrity: sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==} 389 | cpu: [arm64] 390 | os: [linux] 391 | requiresBuild: true 392 | dev: true 393 | optional: true 394 | 395 | /esbuild-linux-mips64le/0.13.15: 396 | resolution: {integrity: sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==} 397 | cpu: [mips64el] 398 | os: [linux] 399 | requiresBuild: true 400 | dev: true 401 | optional: true 402 | 403 | /esbuild-linux-ppc64le/0.13.15: 404 | resolution: {integrity: sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==} 405 | cpu: [ppc64] 406 | os: [linux] 407 | requiresBuild: true 408 | dev: true 409 | optional: true 410 | 411 | /esbuild-netbsd-64/0.13.15: 412 | resolution: {integrity: sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==} 413 | cpu: [x64] 414 | os: [netbsd] 415 | requiresBuild: true 416 | dev: true 417 | optional: true 418 | 419 | /esbuild-openbsd-64/0.13.15: 420 | resolution: {integrity: sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==} 421 | cpu: [x64] 422 | os: [openbsd] 423 | requiresBuild: true 424 | dev: true 425 | optional: true 426 | 427 | /esbuild-sunos-64/0.13.15: 428 | resolution: {integrity: sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==} 429 | cpu: [x64] 430 | os: [sunos] 431 | requiresBuild: true 432 | dev: true 433 | optional: true 434 | 435 | /esbuild-windows-32/0.13.15: 436 | resolution: {integrity: sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==} 437 | cpu: [ia32] 438 | os: [win32] 439 | requiresBuild: true 440 | dev: true 441 | optional: true 442 | 443 | /esbuild-windows-64/0.13.15: 444 | resolution: {integrity: sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==} 445 | cpu: [x64] 446 | os: [win32] 447 | requiresBuild: true 448 | dev: true 449 | optional: true 450 | 451 | /esbuild-windows-arm64/0.13.15: 452 | resolution: {integrity: sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==} 453 | cpu: [arm64] 454 | os: [win32] 455 | requiresBuild: true 456 | dev: true 457 | optional: true 458 | 459 | /esbuild/0.13.15: 460 | resolution: {integrity: sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==} 461 | hasBin: true 462 | requiresBuild: true 463 | optionalDependencies: 464 | esbuild-android-arm64: 0.13.15 465 | esbuild-darwin-64: 0.13.15 466 | esbuild-darwin-arm64: 0.13.15 467 | esbuild-freebsd-64: 0.13.15 468 | esbuild-freebsd-arm64: 0.13.15 469 | esbuild-linux-32: 0.13.15 470 | esbuild-linux-64: 0.13.15 471 | esbuild-linux-arm: 0.13.15 472 | esbuild-linux-arm64: 0.13.15 473 | esbuild-linux-mips64le: 0.13.15 474 | esbuild-linux-ppc64le: 0.13.15 475 | esbuild-netbsd-64: 0.13.15 476 | esbuild-openbsd-64: 0.13.15 477 | esbuild-sunos-64: 0.13.15 478 | esbuild-windows-32: 0.13.15 479 | esbuild-windows-64: 0.13.15 480 | esbuild-windows-arm64: 0.13.15 481 | dev: true 482 | 483 | /estree-walker/2.0.2: 484 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 485 | 486 | /fsevents/2.3.2: 487 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 488 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 489 | os: [darwin] 490 | requiresBuild: true 491 | dev: true 492 | optional: true 493 | 494 | /function-bind/1.1.1: 495 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 496 | dev: true 497 | 498 | /get-intrinsic/1.1.1: 499 | resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==} 500 | dependencies: 501 | function-bind: 1.1.1 502 | has: 1.0.3 503 | has-symbols: 1.0.2 504 | dev: true 505 | 506 | /has-symbols/1.0.2: 507 | resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==} 508 | engines: {node: '>= 0.4'} 509 | dev: true 510 | 511 | /has-tostringtag/1.0.0: 512 | resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} 513 | engines: {node: '>= 0.4'} 514 | dependencies: 515 | has-symbols: 1.0.2 516 | dev: true 517 | 518 | /has/1.0.3: 519 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 520 | engines: {node: '>= 0.4.0'} 521 | dependencies: 522 | function-bind: 1.1.1 523 | dev: true 524 | 525 | /htmlparser2/7.2.0: 526 | resolution: {integrity: sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==} 527 | dependencies: 528 | domelementtype: 2.2.0 529 | domhandler: 4.3.0 530 | domutils: 2.8.0 531 | entities: 3.0.1 532 | dev: true 533 | 534 | /is-core-module/2.8.1: 535 | resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==} 536 | dependencies: 537 | has: 1.0.3 538 | dev: true 539 | 540 | /is-expression/4.0.0: 541 | resolution: {integrity: sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==} 542 | dependencies: 543 | acorn: 7.4.1 544 | object-assign: 4.1.1 545 | dev: true 546 | 547 | /is-promise/2.2.2: 548 | resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} 549 | dev: true 550 | 551 | /is-regex/1.1.4: 552 | resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} 553 | engines: {node: '>= 0.4'} 554 | dependencies: 555 | call-bind: 1.0.2 556 | has-tostringtag: 1.0.0 557 | dev: true 558 | 559 | /js-stringify/1.0.2: 560 | resolution: {integrity: sha1-Fzb939lyTyijaCrcYjCufk6Weds=} 561 | dev: true 562 | 563 | /jsonc-parser/2.3.1: 564 | resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} 565 | dev: true 566 | 567 | /jsonc-parser/3.0.0: 568 | resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==} 569 | dev: true 570 | 571 | /jstransformer/1.0.0: 572 | resolution: {integrity: sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=} 573 | dependencies: 574 | is-promise: 2.2.2 575 | promise: 7.3.1 576 | dev: true 577 | 578 | /lodash-es/4.17.21: 579 | resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} 580 | dev: false 581 | 582 | /lru-cache/6.0.0: 583 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 584 | engines: {node: '>=10'} 585 | dependencies: 586 | yallist: 4.0.0 587 | dev: true 588 | 589 | /magic-string/0.25.7: 590 | resolution: {integrity: sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==} 591 | dependencies: 592 | sourcemap-codec: 1.4.8 593 | dev: false 594 | 595 | /nanoid/3.2.0: 596 | resolution: {integrity: sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==} 597 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 598 | hasBin: true 599 | 600 | /object-assign/4.1.1: 601 | resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} 602 | engines: {node: '>=0.10.0'} 603 | dev: true 604 | 605 | /path-parse/1.0.7: 606 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 607 | dev: true 608 | 609 | /picocolors/1.0.0: 610 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 611 | 612 | /postcss/8.4.6: 613 | resolution: {integrity: sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==} 614 | engines: {node: ^10 || ^12 || >=14} 615 | dependencies: 616 | nanoid: 3.2.0 617 | picocolors: 1.0.0 618 | source-map-js: 1.0.2 619 | 620 | /promise/7.3.1: 621 | resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} 622 | dependencies: 623 | asap: 2.0.6 624 | dev: true 625 | 626 | /pug-attrs/3.0.0: 627 | resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==} 628 | dependencies: 629 | constantinople: 4.0.1 630 | js-stringify: 1.0.2 631 | pug-runtime: 3.0.1 632 | dev: true 633 | 634 | /pug-code-gen/3.0.2: 635 | resolution: {integrity: sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==} 636 | dependencies: 637 | constantinople: 4.0.1 638 | doctypes: 1.1.0 639 | js-stringify: 1.0.2 640 | pug-attrs: 3.0.0 641 | pug-error: 2.0.0 642 | pug-runtime: 3.0.1 643 | void-elements: 3.1.0 644 | with: 7.0.2 645 | dev: true 646 | 647 | /pug-error/2.0.0: 648 | resolution: {integrity: sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==} 649 | dev: true 650 | 651 | /pug-filters/4.0.0: 652 | resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==} 653 | dependencies: 654 | constantinople: 4.0.1 655 | jstransformer: 1.0.0 656 | pug-error: 2.0.0 657 | pug-walk: 2.0.0 658 | resolve: 1.22.0 659 | dev: true 660 | 661 | /pug-lexer/5.0.1: 662 | resolution: {integrity: sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==} 663 | dependencies: 664 | character-parser: 2.2.0 665 | is-expression: 4.0.0 666 | pug-error: 2.0.0 667 | dev: true 668 | 669 | /pug-linker/4.0.0: 670 | resolution: {integrity: sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==} 671 | dependencies: 672 | pug-error: 2.0.0 673 | pug-walk: 2.0.0 674 | dev: true 675 | 676 | /pug-load/3.0.0: 677 | resolution: {integrity: sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==} 678 | dependencies: 679 | object-assign: 4.1.1 680 | pug-walk: 2.0.0 681 | dev: true 682 | 683 | /pug-parser/6.0.0: 684 | resolution: {integrity: sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==} 685 | dependencies: 686 | pug-error: 2.0.0 687 | token-stream: 1.0.0 688 | dev: true 689 | 690 | /pug-runtime/3.0.1: 691 | resolution: {integrity: sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==} 692 | dev: true 693 | 694 | /pug-strip-comments/2.0.0: 695 | resolution: {integrity: sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==} 696 | dependencies: 697 | pug-error: 2.0.0 698 | dev: true 699 | 700 | /pug-walk/2.0.0: 701 | resolution: {integrity: sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==} 702 | dev: true 703 | 704 | /pug/3.0.2: 705 | resolution: {integrity: sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==} 706 | dependencies: 707 | pug-code-gen: 3.0.2 708 | pug-filters: 4.0.0 709 | pug-lexer: 5.0.1 710 | pug-linker: 4.0.0 711 | pug-load: 3.0.0 712 | pug-parser: 6.0.0 713 | pug-runtime: 3.0.1 714 | pug-strip-comments: 2.0.0 715 | dev: true 716 | 717 | /request-light/0.5.7: 718 | resolution: {integrity: sha512-i/wKzvcx7Er8tZnvqSxWuNO5ZGggu2UgZAqj/RyZ0si7lBTXL7kZiI/dWxzxnQjaY7s5HEy1qK21Do4Ncr6cVw==} 719 | dev: true 720 | 721 | /resolve/1.22.0: 722 | resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} 723 | hasBin: true 724 | dependencies: 725 | is-core-module: 2.8.1 726 | path-parse: 1.0.7 727 | supports-preserve-symlinks-flag: 1.0.0 728 | dev: true 729 | 730 | /rollup/2.67.0: 731 | resolution: {integrity: sha512-W83AaERwvDiHwHEF/dfAfS3z1Be5wf7n+pO3ZAO5IQadCT2lBTr7WQ2MwZZe+nodbD+n3HtC4OCOAdsOPPcKZQ==} 732 | engines: {node: '>=10.0.0'} 733 | hasBin: true 734 | optionalDependencies: 735 | fsevents: 2.3.2 736 | dev: true 737 | 738 | /semver/7.3.5: 739 | resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==} 740 | engines: {node: '>=10'} 741 | hasBin: true 742 | dependencies: 743 | lru-cache: 6.0.0 744 | dev: true 745 | 746 | /source-map-js/1.0.2: 747 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 748 | engines: {node: '>=0.10.0'} 749 | 750 | /source-map/0.6.1: 751 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 752 | engines: {node: '>=0.10.0'} 753 | 754 | /sourcemap-codec/1.4.8: 755 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 756 | dev: false 757 | 758 | /supports-preserve-symlinks-flag/1.0.0: 759 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 760 | engines: {node: '>= 0.4'} 761 | dev: true 762 | 763 | /to-fast-properties/2.0.0: 764 | resolution: {integrity: sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=} 765 | engines: {node: '>=4'} 766 | dev: true 767 | 768 | /token-stream/1.0.0: 769 | resolution: {integrity: sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=} 770 | dev: true 771 | 772 | /typescript/4.5.5: 773 | resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==} 774 | engines: {node: '>=4.2.0'} 775 | hasBin: true 776 | dev: true 777 | 778 | /upath/2.0.1: 779 | resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==} 780 | engines: {node: '>=4'} 781 | dev: true 782 | 783 | /vite/2.7.13: 784 | resolution: {integrity: sha512-Mq8et7f3aK0SgSxjDNfOAimZGW9XryfHRa/uV0jseQSilg+KhYDSoNb9h1rknOy6SuMkvNDLKCYAYYUMCE+IgQ==} 785 | engines: {node: '>=12.2.0'} 786 | hasBin: true 787 | peerDependencies: 788 | less: '*' 789 | sass: '*' 790 | stylus: '*' 791 | peerDependenciesMeta: 792 | less: 793 | optional: true 794 | sass: 795 | optional: true 796 | stylus: 797 | optional: true 798 | dependencies: 799 | esbuild: 0.13.15 800 | postcss: 8.4.6 801 | resolve: 1.22.0 802 | rollup: 2.67.0 803 | optionalDependencies: 804 | fsevents: 2.3.2 805 | dev: true 806 | 807 | /void-elements/3.1.0: 808 | resolution: {integrity: sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=} 809 | engines: {node: '>=0.10.0'} 810 | dev: true 811 | 812 | /vscode-css-languageservice/5.1.12: 813 | resolution: {integrity: sha512-293C5C2732Rbhh3opTs+nQBpC5Dd+oYrEA8lc0OWdyt40oYmJ331FV7NMF1SLFSIcOFB5XveLiWUZak2oyc49Q==} 814 | dependencies: 815 | vscode-languageserver-textdocument: 1.0.4 816 | vscode-languageserver-types: 3.16.0 817 | vscode-nls: 5.0.0 818 | vscode-uri: 3.0.3 819 | dev: true 820 | 821 | /vscode-html-languageservice/4.2.1: 822 | resolution: {integrity: sha512-PgaToZVXJ44nFWEBuSINdDgVV6EnpC3MnXBsysR3O5TKcAfywbYeRGRy+Y4dVR7YeUgDvtb+JkJoSkaYC0mxXQ==} 823 | dependencies: 824 | vscode-languageserver-textdocument: 1.0.4 825 | vscode-languageserver-types: 3.16.0 826 | vscode-nls: 5.0.0 827 | vscode-uri: 3.0.3 828 | dev: true 829 | 830 | /vscode-json-languageservice/4.2.0: 831 | resolution: {integrity: sha512-XNawv0Vdy/sUK0S+hGf7cq/qsVAbIniGJr89TvZOqMCNJmpgKTy1e8PL1aWW0uy6BfWMG7vxa5lZb3ypuFtuGQ==} 832 | dependencies: 833 | jsonc-parser: 3.0.0 834 | vscode-languageserver-textdocument: 1.0.4 835 | vscode-languageserver-types: 3.16.0 836 | vscode-nls: 5.0.0 837 | vscode-uri: 3.0.3 838 | dev: true 839 | 840 | /vscode-jsonrpc/8.0.0-next.6: 841 | resolution: {integrity: sha512-6Ld3RYjygn5Ih7CkAtcAwiDQC+rakj2O+PnASfNyYv3sLmm44eJpEKzuPUN30Iy2UB09AZg8T6LBKWTJTEJDVw==} 842 | engines: {node: '>=14.0.0'} 843 | dev: true 844 | 845 | /vscode-languageserver-protocol/3.17.0-next.14: 846 | resolution: {integrity: sha512-iangobY8dL6sFZkOx4OhRPJM9gN0I1caUsOVR+MnPozsqQUtwMXmbIcfaIf0Akp0pd3KhJDPf/tdwRX68QGeeA==} 847 | dependencies: 848 | vscode-jsonrpc: 8.0.0-next.6 849 | vscode-languageserver-types: 3.17.0-next.7 850 | dev: true 851 | 852 | /vscode-languageserver-textdocument/1.0.4: 853 | resolution: {integrity: sha512-/xhqXP/2A2RSs+J8JNXpiiNVvvNM0oTosNVmQnunlKvq9o4mupHOBAnnzH0lwIPKazXKvAKsVp1kr+H/K4lgoQ==} 854 | dev: true 855 | 856 | /vscode-languageserver-types/3.16.0: 857 | resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==} 858 | dev: true 859 | 860 | /vscode-languageserver-types/3.17.0-next.7: 861 | resolution: {integrity: sha512-KH4zdG1qBXxoso61ChgpeoZYyHGJo8bV7Jv4I+fwQ1Ryy59JAxoZ9GAbhR5TeeafHctLcg6RFvY3m8Jqfu17cg==} 862 | dev: true 863 | 864 | /vscode-languageserver/8.0.0-next.8: 865 | resolution: {integrity: sha512-Gq0uqKbOgw7YNwPxMoNCeh7mHKMhG5j6EuoSh+w5pnKd7Eu9a74cagqf9aZDVFWW6GRpqR/Z+1o6EXqDK+g2Tg==} 866 | hasBin: true 867 | dependencies: 868 | vscode-languageserver-protocol: 3.17.0-next.14 869 | dev: true 870 | 871 | /vscode-nls/5.0.0: 872 | resolution: {integrity: sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==} 873 | dev: true 874 | 875 | /vscode-pug-languageservice/0.29.8: 876 | resolution: {integrity: sha512-QHYAzDSJLg7GOLxCZ12qsM0dAM0dPeMSS1t4kKfzLsfpErmZpFzkAIXbidVrNMdMffGZMtTuIlcpEyWHbx96Iw==} 877 | dependencies: 878 | '@volar/code-gen': 0.29.8 879 | '@volar/shared': 0.29.8 880 | '@volar/source-map': 0.29.8 881 | '@volar/transforms': 0.29.8 882 | pug-lexer: 5.0.1 883 | pug-parser: 6.0.0 884 | vscode-languageserver: 8.0.0-next.8 885 | dev: true 886 | 887 | /vscode-typescript-languageservice/0.29.8: 888 | resolution: {integrity: sha512-eecDqHk4WjEvy6VHQ6teHczppQ9yJO2wExCy7yu7WiFj35qbw0h4G6Erv46MvP3ClL8FggFzD7s1qM6vdqJUfw==} 889 | dependencies: 890 | '@volar/shared': 0.29.8 891 | semver: 7.3.5 892 | upath: 2.0.1 893 | vscode-languageserver: 8.0.0-next.8 894 | vscode-languageserver-textdocument: 1.0.4 895 | dev: true 896 | 897 | /vscode-uri/2.1.2: 898 | resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==} 899 | dev: true 900 | 901 | /vscode-uri/3.0.3: 902 | resolution: {integrity: sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==} 903 | dev: true 904 | 905 | /vscode-vue-languageservice/0.29.8: 906 | resolution: {integrity: sha512-qSJdvW5ttyGUB/8uWDKgo8vnIoFnXYlBP4Z/cn54btsRn6ZMw7IJGJU1381e7p/yGvMTLeGbugD53SghbnSa6g==} 907 | dependencies: 908 | '@volar/code-gen': 0.29.8 909 | '@volar/html2pug': 0.29.8 910 | '@volar/shared': 0.29.8 911 | '@volar/source-map': 0.29.8 912 | '@volar/transforms': 0.29.8 913 | '@volar/vue-code-gen': 0.29.8 914 | '@vscode/emmet-helper': 2.8.3 915 | '@vue/reactivity': 3.2.31 916 | '@vue/shared': 3.2.31 917 | request-light: 0.5.7 918 | upath: 2.0.1 919 | vscode-css-languageservice: 5.1.12 920 | vscode-html-languageservice: 4.2.1 921 | vscode-json-languageservice: 4.2.0 922 | vscode-languageserver: 8.0.0-next.8 923 | vscode-languageserver-textdocument: 1.0.4 924 | vscode-pug-languageservice: 0.29.8 925 | vscode-typescript-languageservice: 0.29.8 926 | dev: true 927 | 928 | /vue-chart-3/3.1.3_chart.js@3.7.0+vue@3.2.31: 929 | resolution: {integrity: sha512-iyTw6o4en0VgfAsZKHpH67rGiQMx7Efe9ppdKUon2NrMjxK+XlqPQQ0B/T+YPjLDo4S3hRY+U0YSTaO5mLrY1g==} 930 | peerDependencies: 931 | chart.js: '=> ^3.1.0' 932 | vue: '>= 3' 933 | dependencies: 934 | '@vue/runtime-core': 3.2.31 935 | '@vue/runtime-dom': 3.2.31 936 | chart.js: 3.7.0 937 | csstype: 3.0.11 938 | lodash-es: 4.17.21 939 | vue: 3.2.31 940 | dev: false 941 | 942 | /vue-tsc/0.29.8_typescript@4.5.5: 943 | resolution: {integrity: sha512-pT0wLRjvRuSmB+J4WJT6uuV9mO0KtSSXEAtaVXZQzyk5+DJdbLIQTbRce/TXSkfqt1l1WogO78RjtOJFiMCgfQ==} 944 | hasBin: true 945 | peerDependencies: 946 | typescript: '*' 947 | dependencies: 948 | '@volar/shared': 0.29.8 949 | typescript: 4.5.5 950 | vscode-vue-languageservice: 0.29.8 951 | dev: true 952 | 953 | /vue/3.2.31: 954 | resolution: {integrity: sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==} 955 | dependencies: 956 | '@vue/compiler-dom': 3.2.31 957 | '@vue/compiler-sfc': 3.2.31 958 | '@vue/runtime-dom': 3.2.31 959 | '@vue/server-renderer': 3.2.31_vue@3.2.31 960 | '@vue/shared': 3.2.31 961 | dev: false 962 | 963 | /with/7.0.2: 964 | resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==} 965 | engines: {node: '>= 10.0.0'} 966 | dependencies: 967 | '@babel/parser': 7.17.0 968 | '@babel/types': 7.17.0 969 | assert-never: 1.2.1 970 | babel-walk: 3.0.0-canary-5 971 | dev: true 972 | 973 | /yallist/4.0.0: 974 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 975 | dev: true 976 | -------------------------------------------------------------------------------- /debug/vite/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorgarciaesgi/vue-chart-3/4cbe771d2f1dd87a07e0062ce89fa30ea6dd5955/debug/vite/public/favicon.ico -------------------------------------------------------------------------------- /debug/vite/src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 69 | 70 | 80 | -------------------------------------------------------------------------------- /debug/vite/src/cases/PushData.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 89 | 90 | 100 | -------------------------------------------------------------------------------- /debug/vite/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import { DefineComponent } from 'vue' 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any> 7 | export default component 8 | } 9 | -------------------------------------------------------------------------------- /debug/vite/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /debug/vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "useDefineForClassFields": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "lib": ["esnext", "dom"] 13 | }, 14 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] 15 | } 16 | -------------------------------------------------------------------------------- /debug/vite/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()] 7 | }) 8 | -------------------------------------------------------------------------------- /debug/vue-cli/.eslintignore: -------------------------------------------------------------------------------- 1 | src/dist -------------------------------------------------------------------------------- /debug/vue-cli/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true, 6 | }, 7 | parserOptions: { 8 | parser: '@typescript-eslint/parser', 9 | ecmaFeatures: { 10 | jsx: true, 11 | }, 12 | useJSXTextNode: true, 13 | extraFileExtensions: ['.vue'], 14 | }, 15 | extends: ['prettier', 'prettier/vue', 'prettier/@typescript-eslint'], 16 | plugins: ['prettier', '@typescript-eslint'], 17 | }; 18 | -------------------------------------------------------------------------------- /debug/vue-cli/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /debug/vue-cli/README.md: -------------------------------------------------------------------------------- 1 | # vue3 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /debug/vue-cli/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/cli-plugin-babel/preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /debug/vue-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "chart.js": "^3.7.1", 12 | "core-js": "^3.19.1", 13 | "vue": "^3.2.31", 14 | "vue-chart-3": "^3.1.4" 15 | }, 16 | "devDependencies": { 17 | "@typescript-eslint/eslint-plugin": "^5.10.2", 18 | "@typescript-eslint/parser": "^5.10.2", 19 | "@vue/cli-plugin-babel": "~4.5.15", 20 | "@vue/cli-plugin-typescript": "~4.5.15", 21 | "@vue/cli-service": "~4.5.15", 22 | "@vue/compiler-sfc": "^3.2.29", 23 | "@vue/eslint-config-prettier": "^7.0.0", 24 | "@vue/eslint-config-typescript": "^10.0.0", 25 | "eslint": "^8.8.0", 26 | "eslint-plugin-prettier": "^4.0.0", 27 | "eslint-plugin-vue": "^8.4.1", 28 | "prettier": "^2.2.1", 29 | "typescript": "^4.5.2" 30 | }, 31 | "browserslist": [ 32 | "> 1%", 33 | "last 2 versions", 34 | "not dead" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /debug/vue-cli/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorgarciaesgi/vue-chart-3/4cbe771d2f1dd87a07e0062ce89fa30ea6dd5955/debug/vue-cli/public/favicon.ico -------------------------------------------------------------------------------- /debug/vue-cli/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /debug/vue-cli/src/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 85 | 86 | 96 | -------------------------------------------------------------------------------- /debug/vue-cli/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './App.vue'; 3 | 4 | createApp(App).mount('#app'); 5 | -------------------------------------------------------------------------------- /debug/vue-cli/src/mixed.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Chart, 3 | } from 'chart.js'; 4 | 5 | declare module 'chart.js' { 6 | export interface ChartTypeRegistry { 7 | mixedBarLine: { 8 | chartOptions: CoreChartOptions<'mixedBarLine'>; 9 | }; 10 | } 11 | } -------------------------------------------------------------------------------- /debug/vue-cli/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { DefineComponent } from 'vue'; 3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 4 | const component: DefineComponent<{}, {}, any>; 5 | export default component; 6 | } 7 | -------------------------------------------------------------------------------- /debug/vue-cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": false, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": ["webpack-env"], 15 | "paths": { 16 | "@/*": ["src/*"] 17 | }, 18 | "lib": ["esnext", "dom", "dom.iterable", "scripthost"] 19 | }, 20 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"], 21 | "exclude": ["node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /docs/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | import { defineUserConfig } from 'vuepress'; 2 | import type { DefaultThemeOptions } from 'vuepress'; 3 | import meta from '../../package.json'; 4 | 5 | export default defineUserConfig({ 6 | lang: 'en-US', 7 | title: 'vue-chart-3', 8 | description: 'A simple wrapper around Chart.js 3 for Vue 2 & 3', 9 | locales: { 10 | '/': { 11 | lang: 'en-US', 12 | title: 'vue-chart-3', 13 | description: 'Chart.js v3 for Vue 2 and Vue 3', 14 | }, 15 | }, 16 | plugins: [ 17 | [ 18 | '@vuepress/plugin-docsearch', 19 | { 20 | appId: 'BH4D9OD16A', 21 | apiKey: 'f8206c1e05cedf8dcf7769bb3b87ada3', 22 | indexName: 'vue-chart-3', 23 | searchParameters: { facetFilters: ['lang:en-US'] }, 24 | }, 25 | ], 26 | ], 27 | themeConfig: { 28 | repo: 'victorgarciaesgi/vue-chart-3', 29 | docsDir: 'docs', 30 | editLinks: true, 31 | lastUpdated: true, 32 | logo: '/images/logo.svg', 33 | locales: { 34 | '/': { 35 | label: 'English', 36 | selectText: 'Languages', 37 | editLinkText: 'Edit this page on GitHub', 38 | sidebar: { 39 | '/guide/': [ 40 | '/guide/README.md', 41 | { 42 | text: 'Configuration', 43 | children: ['/guide/configuration/', '/guide/configuration/plugins'], 44 | }, 45 | { 46 | text: 'Usage', 47 | children: [ 48 | '/guide/usage/', 49 | '/guide/usage/chart-instance', 50 | '/guide/usage/dynamic-data', 51 | '/guide/usage/manual-update', 52 | '/guide/usage/typescript', 53 | '/guide/usage/actions', 54 | ], 55 | }, 56 | { 57 | text: 'Examples', 58 | children: [ 59 | '/guide/examples/vue3', 60 | '/guide/examples/vue2-composition', 61 | '/guide/examples/vue2-class', 62 | '/guide/examples/nuxt2', 63 | ], 64 | }, 65 | ], 66 | '/components': [ 67 | '/components/README.md', 68 | { 69 | text: 'Chart hooks (beta)', 70 | children: ['/components/hooks/', '/components/hooks/example'], 71 | }, 72 | ], 73 | }, 74 | navbar: [ 75 | { 76 | text: 'Guide', 77 | link: '/guide/', 78 | }, 79 | { 80 | text: 'Components', 81 | link: '/components/', 82 | }, 83 | ], 84 | }, 85 | }, 86 | }, 87 | head: [ 88 | [ 89 | 'link', 90 | { 91 | rel: 'icon', 92 | type: 'image/x-icon', 93 | sizes: '48x48', 94 | href: `/favicon.ico`, 95 | }, 96 | ], 97 | [ 98 | 'meta', 99 | { 100 | property: 'og:image', 101 | content: 'https://vue-chart-3.netlify.com/assets/logo.png', 102 | }, 103 | ], 104 | [ 105 | 'meta', 106 | { 107 | property: 'twitter:image', 108 | content: 'https://vue-chart-3.netlify.com/assets/logo.png', 109 | }, 110 | ], 111 | [ 112 | 'meta', 113 | { 114 | property: 'og:description', 115 | content: meta.description, 116 | }, 117 | ], 118 | [ 119 | 'meta', 120 | { 121 | name: 'description', 122 | content: meta.description, 123 | }, 124 | ], 125 | 126 | [ 127 | 'meta', 128 | { 129 | name: 'keywords', 130 | content: meta.keywords.join(','), 131 | }, 132 | ], 133 | ], 134 | }); 135 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorgarciaesgi/vue-chart-3/4cbe771d2f1dd87a07e0062ce89fa30ea6dd5955/docs/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/.vuepress/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorgarciaesgi/vue-chart-3/4cbe771d2f1dd87a07e0062ce89fa30ea6dd5955/docs/.vuepress/public/images/logo.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | chartjs-logo-svg 3 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | scroll-behavior: smooth; 3 | --c-brand: #ff6384; 4 | // brand colors 5 | 6 | // background colors 7 | --c-bg: #ffffff; 8 | --c-bg-light: #f3f4f5; 9 | --c-bg-lighter: #eeeeee; 10 | --c-bg-navbar: var(--c-bg); 11 | --c-bg-sidebar: var(--c-bg); 12 | --c-bg-arrow: #cccccc; 13 | 14 | // text colors 15 | --c-text: #2c3e50; 16 | --c-text-accent: var(--c-brand); 17 | --c-text-light: #3a5169; 18 | --c-text-lighter: #4e6e8e; 19 | --c-text-lightest: #6a8bad; 20 | --c-text-quote: #999999; 21 | 22 | // border colors 23 | --c-border: #eaecef; 24 | --c-border-dark: #dfe2e5; 25 | 26 | // custom container colors 27 | --c-tip: #42b983; 28 | --c-tip-bg: var(--c-bg-light); 29 | --c-tip-title: var(--c-text); 30 | --c-tip-text: var(--c-text); 31 | --c-tip-text-accent: var(--c-text-accent); 32 | --c-warning: #e7c000; 33 | --c-warning-bg: #fffae3; 34 | --c-warning-title: #ad9000; 35 | --c-warning-text: #746000; 36 | --c-warning-text-accent: var(--c-text); 37 | --c-danger: #cc0000; 38 | --c-danger-bg: #ffe0e0; 39 | --c-danger-title: #990000; 40 | --c-danger-text: #660000; 41 | --c-danger-text-accent: var(--c-text); 42 | --c-details-bg: #eeeeee; 43 | 44 | // badge component colors 45 | --c-badge-tip: var(--c-tip); 46 | --c-badge-warning: var(--c-warning); 47 | --c-badge-danger: var(--c-danger); 48 | 49 | // transition vars 50 | --t-color: 0.3s ease; 51 | --t-transform: 0.3s ease; 52 | 53 | // code blocks vars 54 | --code-bg-color: #282c34; 55 | --code-hl-bg-color: rgba(0, 0, 0, 0.66); 56 | --code-ln-color: #9e9e9e; 57 | --code-ln-wrapper-width: 3.5rem; 58 | 59 | // font vars 60 | --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 61 | 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 62 | --font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 63 | 64 | // layout vars 65 | --navbar-height: 3.6rem; 66 | --navbar-padding-v: 0.7rem; 67 | --navbar-padding-h: 1.5rem; 68 | --sidebar-width: 20rem; 69 | --sidebar-width-mobile: calc(var(--sidebar-width) * 0.82); 70 | --content-width: 740px; 71 | --homepage-width: 960px; 72 | 73 | // plugin-back-to-top 74 | .back-to-top { 75 | --back-to-top-color: var(--c-brand); 76 | --back-to-top-color-hover: var(--c-brand-light); 77 | } 78 | 79 | // plugin-docsearch 80 | .DocSearch { 81 | --docsearch-primary-color: var(--c-brand); 82 | --docsearch-text-color: var(--c-text); 83 | --docsearch-highlight-color: var(--c-brand); 84 | --docsearch-muted-color: var(--c-text-quote); 85 | --docsearch-container-background: rgba(9, 10, 17, 0.8); 86 | --docsearch-modal-background: var(--c-bg-light); 87 | --docsearch-searchbox-background: var(--c-bg-lighter); 88 | --docsearch-searchbox-focus-background: var(--c-bg); 89 | --docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand); 90 | --docsearch-hit-color: var(--c-text-light); 91 | --docsearch-hit-active-color: var(--c-bg); 92 | --docsearch-hit-background: var(--c-bg); 93 | --docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark); 94 | --docsearch-footer-background: var(--c-bg); 95 | } 96 | 97 | // plugin-medium-zoom 98 | .medium-zoom-overlay { 99 | --medium-zoom-bg-color: var(--c-bg); 100 | } 101 | 102 | // plugin-nprogress 103 | #nprogress { 104 | --nprogress-color: var(--c-brand); 105 | } 106 | 107 | // plugin-pwa-popup 108 | .pwa-popup { 109 | --pwa-popup-text-color: var(--c-text); 110 | --pwa-popup-bg-color: var(--c-bg); 111 | --pwa-popup-border-color: var(--c-brand); 112 | --pwa-popup-shadow: 0 4px 16px var(--c-brand); 113 | --pwa-popup-btn-text-color: var(--c-bg); 114 | --pwa-popup-btn-bg-color: var(--c-brand); 115 | --pwa-popup-btn-hover-bg-color: var(--c-brand-light); 116 | } 117 | 118 | // plugin-search 119 | .search-box { 120 | --search-bg-color: var(--c-bg); 121 | --search-accent-color: var(--c-brand); 122 | --search-text-color: var(--c-text); 123 | --search-border-color: var(--c-border); 124 | 125 | --search-item-text-color: var(--c-text-lighter); 126 | --search-item-focus-bg-color: var(--c-bg-light); 127 | } 128 | } 129 | 130 | html.dark { 131 | // brand colors 132 | --c-brand: #ff6384; 133 | --c-brand-light: #ed728c; 134 | 135 | // background colors 136 | --c-bg: #22272e; 137 | --c-bg-light: #2b313a; 138 | --c-bg-lighter: #262c34; 139 | 140 | // text colors 141 | --c-text: #adbac7; 142 | --c-text-light: #96a7b7; 143 | --c-text-lighter: #8b9eb0; 144 | --c-text-lightest: #8094a8; 145 | 146 | // border colors 147 | --c-border: #3e4c5a; 148 | --c-border-dark: #34404c; 149 | 150 | // custom container colors 151 | --c-tip: #318a62; 152 | --c-warning: #ceab00; 153 | --c-warning-bg: #7e755b; 154 | --c-warning-title: #ceac03; 155 | --c-warning-text: #362e00; 156 | --c-danger: #940000; 157 | --c-danger-bg: #806161; 158 | --c-danger-title: #610000; 159 | --c-danger-text: #3a0000; 160 | --c-details-bg: #323843; 161 | 162 | // code blocks vars 163 | --code-hl-bg-color: #363b46; 164 | } 165 | 166 | // plugin-docsearch 167 | html.dark .DocSearch { 168 | --docsearch-logo-color: var(--c-text); 169 | --docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309; 170 | --docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 171 | 0 2px 2px 0 rgba(3, 4, 9, 0.3); 172 | --docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21); 173 | --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5), 0 -4px 8px 0 rgba(0, 0, 0, 0.2); 174 | } 175 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/palette.scss: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /images/logo.svg 4 | actions: 5 | - text: 'Get Started →' 6 | link: '/guide/' 7 | footer: MIT Licensed | Copyright © 2021-present Victor Garcia 8 | --- 9 | 10 |
11 |
12 |

Simple

13 |

Simply import the chart component you want and use it out of the box

14 |
15 |
16 |

Typescript safety

17 |

All props are linked to Chart.js types (with Volar)

18 |
19 |
20 |

Versatile

21 |

Works with both Vue 2 and Vue 3 with the power of vue-demi

22 |
23 | 24 |
25 | -------------------------------------------------------------------------------- /docs/components/README.md: -------------------------------------------------------------------------------- 1 | # Components information 2 | 3 | ## List of all components 4 | 5 | - BarChart 6 | - DoughnutChart 7 | - LineChart 8 | - PieChart 9 | - PolarAreaChart 10 | - RadarChart 11 | - BubbleChart 12 | - ScatterChart 13 | 14 | ## All components props 15 | 16 | | Prop | Type | Default | 17 | | ---------------- | ------------------------------ | ------- | 18 | | 'chartData' | ChartJs.ChartData | 19 | | 'options' | ChartJs.ChartOptions | 20 | | 'plugins' | ChartJs.Plugin[] | 21 | | 'cssClasses' | string | 22 | | 'width' | number | 400 | 23 | | 'height' | number | 400 | 24 | | 'onChartRender' | (chartInstance: Chart) => void | 25 | | 'onChartUpdate' | (chartInstance: Chart) => void | 26 | | 'onChartDestroy' | () => void | 27 | | 'onLabelsUpdate' | () => void | 28 | 29 | ## Data accessible by reference 30 | 31 | | Prop | Type | 32 | | --------------- | ----------------- | 33 | | 'chartInstance' | Chart | 34 | | 'canvasRef' | HtmlCanvasElement | 35 | | 'renderChart' | () => void | 36 | 37 | ## Events emitted by all components 38 | 39 | | Event | Payload | 40 | | --------------- | -------------------- | 41 | | 'chart:render' | chartInstance: Chart | 42 | | 'chart:update' | chartInstance: Chart | 43 | | 'chart:destroy' | - | 44 | | 'labels:update' | - | 45 | -------------------------------------------------------------------------------- /docs/components/hooks/README.md: -------------------------------------------------------------------------------- 1 | # Hooks 2 | 3 | ## Guide 4 | 5 | ::: warning 6 | Hooks are still in alpha 7 | ::: 8 | 9 | `vue-chart-3` also provides fully typed hooks compatible with Vue 2 and Vue 3 using `vue-demi`. 10 | 11 | They are not mandatory, but they simplify the usage of chart components. 12 | 13 | Each component has its corresponding hooks. Ex: `Barchart` will have `useBarChart`. 14 | 15 | ## Usage 16 | 17 | Using the `useXXXChart` will clean up your code as it provides a shortcut for props and ref 18 | 19 | Declaring it give you access to `xxxChartProps` and `xxxChartRef`. 20 | 21 | For `BarChart` you can import `useBarChart` from `vue-chart-3` and use it like this 22 | 23 | ```ts 24 | export default defineComponent({ 25 | ..., 26 | setup() { 27 | const { barChartProps, barChartRef, update } = useBarChart({ 28 | chartData: {}, //... 29 | plugins: [] 30 | }); 31 | 32 | return { barChartProps, barChartRef } 33 | } 34 | }) 35 | 36 | ``` 37 | 38 | Then you can use the `barChartProps` to fill the props of the component 39 | 40 | ```html 41 | 42 | ``` 43 | 44 | ## Manual update 45 | 46 | This hook also returns a helper function to manually update the ChartInstance 47 | 48 | ```ts 49 | const { barChartProps, barChartRef, update } = useBarChart({...}) 50 | ``` 51 | 52 | ## Custom hook 53 | 54 | If you have created a custom Chart component, you can also create your custom hook 55 | 56 | ```ts 57 | import {defineChartComponent, defineChartHook} from 'vue-chart-3'; 58 | 59 | const MatrixChart = defineChartComponent('matrix-chart', 'matrix'); 60 | const useMatrixChart = defineChartHook('matrix'); 61 | 62 | export default defineComponent({ 63 | ..., 64 | components: { 65 | MatrixChart 66 | }, 67 | setup() { 68 | const { matrixChartProps, matrixChartRef } = useMatrixChart({ 69 | chartData: {}, 70 | plugins: [] 71 | }); 72 | 73 | return { matrixChartProps, matrixChartRef } 74 | } 75 | }) 76 | 77 | ``` 78 | 79 | ## Usage with render function 80 | 81 | Usage with render function is supported, with just a parameter. The reason is that in templates, Vue needs a `string` ref (ex: ref='inputRef'), but in render functions, it needs the ref accessor (ex: ref={inputRef}) 82 | 83 | ```ts 84 | export default defineComponent({ 85 | ..., 86 | setup() { 87 | const { barChartProps, barChartRef } = useBarChart({ 88 | chartData: {}, 89 | plugins: [], 90 | jsx: true // <---- 91 | }); 92 | 93 | return () => ( 94 | 95 | ) 96 | } 97 | }) 98 | 99 | ``` 100 | -------------------------------------------------------------------------------- /docs/components/hooks/example.md: -------------------------------------------------------------------------------- 1 | # Full Example 2 | 3 | ```vue 4 | 10 | 11 | 49 | 50 | 60 | ``` 61 | -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | ## Introduction 4 | 5 | vue-chart-3 is rewrite of `vue-chartjs` for [Chart.js 3](https://www.chartjs.org/) for Vue 2 & 3, but written in Typescript and Vue Composition API. 6 | 7 | # Installation 8 | 9 | ## For Vue 3 10 | 11 | ```bash 12 | npm i vue-chart-3 chart.js 13 | #or 14 | yarn add vue-chart-3 chart.js 15 | #or 16 | pnpm i vue-chart-3 chart.js 17 | ``` 18 | 19 | ## For Vue 2 20 | 21 | ```bash 22 | npm i vue-chart-3@legacy chart.js 23 | #or 24 | yarn add vue-chart-3@legacy chart.js 25 | #or 26 | pnpm i vue-chart-3@legacy chart.js 27 | ``` 28 | 29 | ## Important notes 30 | 31 | ### Using with Vue 3 or Vue 2 32 | 33 | This package works with version 2.x and 3.x of Vue. 34 | 35 | For Vue 2 users, you will have to keep `2.x` version of `vue-chart-3` 36 | 37 | - Vue 3 works out-of-the-box 38 | - Vue 2 requires `@vue/composition-api` package to also be installed and registered, to provide Vue 3's [Composition API](https://v3.vuejs.org/guide/composition-api-introduction.html) features like `ref, defineComponent, computed, reactive`. 39 | 40 | ⚠️ Since `2.0.3` (for Vue 2 users), Vue composition api will not register itself. Update your project if you didn't do it manually! 41 | 42 | ### Chart.js (v3) 43 | 44 | Chart.js v3 is now tree-shakable, so make sure to import and register the chart components you need. See [Chart.js API](https://www.chartjs.org/docs/master/api/) for all available imports. 45 | 46 | [Learn more about Chart.js tree-shaking](https://www.chartjs.org/docs/master/getting-started/integration.html#bundlers-webpack-rollup-etc) 47 | 48 | For example, if you want to create a Doughnut chart and tree-shake the unused other components, it might look like this: 49 | 50 | ```ts 51 | import { Chart, DoughnutController, ArcElement, Tooltip } from 'chart.js'; 52 | Chart.register(DoughnutController, ArcElement, Tooltip); 53 | ``` 54 | 55 | Or if you want all components of Chart.js (but lose the benefits of tree-shaking), use this: 56 | 57 | ```ts 58 | import { Chart, registerables } from 'chart.js'; 59 | Chart.register(...registerables); 60 | ``` 61 | 62 | Unlike `vue-chartjs`, there is no need to re-create each component with mixins and reactive props, etc. with this package. Thanks to `@vue/composition-api`, all of this is possible just by importing the corresponding component. 63 | 64 | (Thanks to [@nwittwer](https://github.com/nwittwer) for upgraded notes) 65 | -------------------------------------------------------------------------------- /docs/guide/configuration/README.md: -------------------------------------------------------------------------------- 1 | # Pre-requisites 2 | 3 | ## Vue 2 4 | 5 | You need to have `@vue/composition-api` installed and registered. 6 | 7 | ## Vite.js + Vue 3 8 | 9 | Nothing required, it works out of the box! 10 | 11 | ## Nuxt 2 / Nuxt bridge 12 | 13 | - Create a plugin in `/plugins/chartjs.js` 14 | 15 | ```js 16 | import { Chart, registerables } from 'chart.js'; 17 | Chart.register(...registerables); 18 | ``` 19 | 20 | - Then register it in your `nuxt.config.[js|ts]` 21 | 22 | ```js 23 | export default { 24 | plugins: [{ src: '~/plugins/chartjs.js', ssr: false }], 25 | build: { 26 | // Transpile ESM modules because Nuxt 2 uses CommonJS for building server and `vue-chart-3` uses `lodash-es` internaly 27 | transpile: ['lodash-es', 'vue-chart-3'], 28 | }, 29 | }; 30 | ``` 31 | 32 | (Thanks to [@mirkopoloni](https://github.com/mirkopoloni) for additional Nuxt tips) 33 | 34 | ## Nuxt 3 35 | 36 | Create a plugin in `/plugins/chartjs.client.ts` 37 | 38 | ```ts 39 | import { defineNuxtPlugin } from '#app'; 40 | 41 | // Workaround because chart.js doesn't provide an default export 42 | import * as ChartJs from 'chart.js'; 43 | const { Chart, registerables } = ChartJs; 44 | 45 | export default defineNuxtPlugin(() => { 46 | Chart.register(...registerables); 47 | }); 48 | ``` 49 | 50 | Nuxt 3 will register the plugins itself thanks to the `**.client.ts`, it knows that it needs to be call only client-side 51 | -------------------------------------------------------------------------------- /docs/guide/configuration/plugins.md: -------------------------------------------------------------------------------- 1 | # Supporting plugins 2 | 3 | You can use `defineChartComponent` to create ChartJs plugins components 4 | 5 | Example: 6 | 7 | ```ts 8 | import { Chart, registerables } from 'chart.js'; 9 | import { defineChartComponent } from 'vue-chart-3'; 10 | import { MatrixController, MatrixElement } from 'chartjs-chart-matrix'; 11 | 12 | Chart.register(MatrixController, MatrixElement, ...registerables); 13 | 14 | const Matrix = defineChartComponent('MatrixChart', 'matrix'); 15 | // You can now use this component anywhere 16 | ``` 17 | 18 | If you are using Typescript, you have to augment the interface `ChartTypeRegistry` from `chart.js` manually. 19 | 20 | The plugins for Chart.js are usually typed, but if they aren't you can do it manually 21 | 22 | (Example taken from [chartjs-chart-matrix](https://github.com/kurkle/chartjs-chart-matrix/blob/next/types/index.esm.d.ts)) 23 | 24 | ```ts 25 | declare module 'chart.js' { 26 | export interface ChartTypeRegistry { 27 | matrix: { 28 | chartOptions: CoreChartOptions<'matrix'>; 29 | datasetOptions: MatrixControllerDatasetOptions<'matrix'>; 30 | defaultDataPoint: MatrixDataPoint; 31 | parsedDataType: MatrixDataPoint; 32 | scales: never; 33 | }; 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/guide/examples.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victorgarciaesgi/vue-chart-3/4cbe771d2f1dd87a07e0062ce89fa30ea6dd5955/docs/guide/examples.md -------------------------------------------------------------------------------- /docs/guide/examples/nuxt2.md: -------------------------------------------------------------------------------- 1 | # Nuxt 2 + SSR + composition API 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/guide/examples/vue2-class.md: -------------------------------------------------------------------------------- 1 | # Vue 2 + Typescript + class API 2 | 3 | -------------------------------------------------------------------------------- /docs/guide/examples/vue2-composition.md: -------------------------------------------------------------------------------- 1 | # Vue 2 + composition API + plugins 2 | 3 | 9 | -------------------------------------------------------------------------------- /docs/guide/examples/vue3.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Typescript 2 | 3 | 9 | -------------------------------------------------------------------------------- /docs/guide/usage/README.md: -------------------------------------------------------------------------------- 1 | # Using components 2 | 3 | You just have to import the corresponding component matching the type of chart you want, the list of components can be found [here](/components) 4 | 5 | Here is an example with static data 6 | 7 | ```vue 8 | 11 | 12 | 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/guide/usage/actions.md: -------------------------------------------------------------------------------- 1 | # Programmatic Event Triggers 2 | 3 | Charts.js Programmatic events are a way to call plugin actions. 4 | ([Programmatic Event Triggers](Programmatic Event Triggers)) 5 | 6 | In `vue-chart-3`, it works the same way by accessing the `chartInstance` in the template ref. 7 | 8 | Example with a plugin like [chartjs-plugin-zoom](https://www.chartjs.org/chartjs-plugin-zoom/) 9 | 10 | ```ts 11 | barChartRef.value.chartInstance.resetZoom(); 12 | ``` 13 | 14 | Example in [Vue 2 demo](https://vue-chart-3.netlify.app) 15 | -------------------------------------------------------------------------------- /docs/guide/usage/chart-instance.md: -------------------------------------------------------------------------------- 1 | # Accessing Canvas Ref and chartInstance 2 | 3 | The Chart.js `chartInstance` and `canvasRef` are accessible by the component's reference using `ref`. 4 | It is also passed in events (`chart-render` and `chart-update`) 5 | 6 | ```vue 7 | 10 | 11 | 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/guide/usage/dynamic-data.md: -------------------------------------------------------------------------------- 1 | # Reactive data and options 2 | 3 | Each component will trigger an update on the chart when the data passed thought `chart-data` and `options` changes. 4 | 5 | ```vue 6 | 12 | 13 | 56 | ``` 57 | -------------------------------------------------------------------------------- /docs/guide/usage/manual-update.md: -------------------------------------------------------------------------------- 1 | # Manual update 2 | 3 | When accessing to the template ref, you can call the helper function `update`, which will force update the ChartInstance 4 | 5 | ```vue 6 | 9 | 10 | 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/guide/usage/typescript.md: -------------------------------------------------------------------------------- 1 | # Typescript 2 | 3 | Each component props is properly typed and should be throwing errors if you are using [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) 4 | 5 | ## Code example 6 | 7 | ```vue 8 | 14 | 15 | 58 | ``` 59 | 60 | ## Helper types 61 | 62 | ### `ExtractComponentData` 63 | 64 | This component is useful if you want to access the Chart component ref. 65 | 66 | Ex: 67 | 68 | ```ts 69 | setup() { 70 | const doughnutRef = ref>() 71 | 72 | foo() { 73 | doughnutRef.value?.chartInstance.toBase64Image(); 74 | } 75 | } 76 | ``` 77 | 78 | ### `ExtractComponentProps` 79 | 80 | This type will extracts prop types from the component if you want to type your `v-bind`. 81 | 82 | Ex: 83 | 84 | ```ts 85 | setup() { 86 | const barChartProps = computed>(() => ({ 87 | chartData: {...}, 88 | options: {} 89 | })) 90 | } 91 | ``` 92 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "commonjs" 3 | } 4 | -------------------------------------------------------------------------------- /media/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | chartjs-logo-svg 3 | 4 | 5 | 6 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-chart-3", 3 | "version": "3.1.8", 4 | "description": "📊 A simple wrapper around Chart.js 3 for Vue 2 & 3", 5 | "license": "MIT", 6 | "scripts": { 7 | "dev": "npm run prepack -- --watch", 8 | "prepack": "tsup", 9 | "test": "vitest run", 10 | "test:watch": "vitest", 11 | "publish:alpha": "npm publish --tag next", 12 | "deploy": "npm run test && npm publish", 13 | "docs:dev": "vuepress dev docs", 14 | "docs:build": " vuepress build docs" 15 | }, 16 | "author": { 17 | "name": "Victor Garcia", 18 | "url": "https://github.com/victorgarciaesgi" 19 | }, 20 | "type": "module", 21 | "exports": { 22 | ".": { 23 | "import": "./dist/index.js", 24 | "require": "./dist/index.cjs" 25 | } 26 | }, 27 | "main": "./dist/index.cjs", 28 | "types": "./dist/index.d.ts", 29 | "files": [ 30 | "dist" 31 | ], 32 | "peerDependencies": { 33 | "chart.js": "=> ^3.1.0", 34 | "vue": ">= 3" 35 | }, 36 | "dependencies": { 37 | "@vue/runtime-core": "latest", 38 | "@vue/runtime-dom": "latest", 39 | "csstype": "latest", 40 | "lodash-es": "latest" 41 | }, 42 | "devDependencies": { 43 | "@types/chart.js": "^2.9.35", 44 | "@types/lodash-es": "^4.17.6", 45 | "@types/node": "^17.0.19", 46 | "@types/pascalcase": "^1.0.1", 47 | "@vue/cli": "^5.0.1", 48 | "@vue/runtime-core": "^3.2.31", 49 | "@vue/runtime-dom": "^3.2.31", 50 | "@vue/test-utils": "^2.0.0-rc.17", 51 | "@vuepress/plugin-docsearch": "^2.0.0-beta.35", 52 | "@vuepress/plugin-palette": "^2.0.0-beta.35", 53 | "chart.js": "^3.7.1", 54 | "chartjs-test-utils": "^0.4.0", 55 | "happy-dom": "^2.40.0", 56 | "jest-canvas-mock": "^2.3.1", 57 | "jsdom": "^19.0.0", 58 | "tsup": "^5.11.13", 59 | "typescript": "^4.5.5", 60 | "vite": "^2.8.4", 61 | "vitest": "^0.5.1", 62 | "vue": "^3.2.31", 63 | "vue-chart-3": "latest", 64 | "vuepress": "^2.0.0-beta.35", 65 | "vuepress-vite": "^2.0.0-beta.35" 66 | }, 67 | "repository": { 68 | "type": "git", 69 | "url": "git+https://github.com/victorgarciaesgi/vue-chart-3.git" 70 | }, 71 | "homepage": "https://vue-chart-3.netlify.app/", 72 | "gitHead": "b17a8646d048947e3ec54865873ff0ff1ab19e78", 73 | "keywords": [ 74 | "vue chartjs 3", 75 | "vue chart.js 3", 76 | "chartjs 3", 77 | "vue chartjs", 78 | "chartjs vue", 79 | "chartjs 3 vue", 80 | "chartjs vue3", 81 | "chartjs vue 3", 82 | "vue chart.js" 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /src/core/component.builder.ts: -------------------------------------------------------------------------------- 1 | import type { Chart, ChartData, ChartDataset, ChartOptions, ChartType, Plugin } from 'chart.js'; 2 | import * as Chartjs from 'chart.js'; 3 | import { cloneDeep, isEmpty, isEqual, isObject } from 'lodash-es'; 4 | import { pascalCase } from '../utils'; 5 | import { 6 | ComponentOptionsMixin, 7 | computed, 8 | ComputedOptions, 9 | defineComponent, 10 | DefineComponent, 11 | h, 12 | MethodOptions, 13 | onBeforeUnmount, 14 | onMounted, 15 | PropType, 16 | ref, 17 | shallowRef, 18 | watch, 19 | } from 'vue'; 20 | import { ChartComponentEmits } from '.'; 21 | import type { StyleValue } from '../misc'; 22 | import type { ChartPropsOptions, ComponentData } from './component.types'; 23 | 24 | /** Builder method to create a component based on Chart.js chart type 25 | * 26 | * @param chartName the id of the chart component 27 | * @param chartType the Chart.js chart type to use 28 | * 29 | * @example 30 | * 31 | * ```ts 32 | * const MatrixChart = defineChartComponent('matrix-chart', 'matrix'); 33 | * ``` 34 | */ 35 | export const defineChartComponent = ( 36 | chartName: string, 37 | chartType: TType 38 | ): DefineComponent< 39 | ChartPropsOptions, 40 | ComponentData, 41 | unknown, 42 | ComputedOptions, 43 | MethodOptions, 44 | ComponentOptionsMixin, 45 | ComponentOptionsMixin, 46 | ChartComponentEmits 47 | > => { 48 | const propsDefs: ChartPropsOptions = { 49 | chartData: { type: Object as PropType>, required: true }, 50 | options: { type: Object as PropType>, required: false }, 51 | chartId: { default: chartName, type: String }, 52 | width: { default: 400, type: Number }, 53 | height: { default: 400, type: Number }, 54 | cssClasses: { type: String, default: '' }, 55 | styles: { type: Object as PropType }, 56 | plugins: { type: Array as PropType, default: () => [] }, 57 | onLabelsUpdate: { type: Function as PropType<() => void> }, 58 | onChartUpdate: { type: Function as PropType<(chartInstance: Chart) => void> }, 59 | onChartDestroy: { type: Function as PropType<() => void> }, 60 | onChartRender: { type: Function as PropType<(chartInstance: Chart) => void> }, 61 | }; 62 | 63 | const componentName = pascalCase(chartName); 64 | 65 | return defineComponent({ 66 | name: componentName, 67 | props: propsDefs, 68 | emits: { 69 | 'labels:update': () => true, 70 | 'chart:update': (chartInstance: Chart) => true, 71 | 'chart:destroy': () => true, 72 | 'chart:render': (chartInstance: Chart) => true, 73 | } as ChartComponentEmits, 74 | setup(props, { emit, expose }) { 75 | const canvasRef = ref(null); 76 | 77 | const canvasId = `${props.chartId}`; 78 | 79 | let chartInstance = shallowRef | null>(null); 80 | 81 | watch(() => props.chartData, watchHandler, { deep: true }); 82 | watch( 83 | () => props.options, 84 | (newOptions) => { 85 | if (chartInstance.value && newOptions) { 86 | chartInstance.value.options = cloneDeep(newOptions) as any; 87 | handleChartUpdate(); 88 | } 89 | }, 90 | { deep: true } 91 | ); 92 | 93 | function watchHandler(newData: ChartData) { 94 | if (chartInstance.value) { 95 | let chart = chartInstance.value; 96 | if (!isEqual(newData.labels, chartInstance.value.data.labels)) { 97 | chart.data.labels = newData.labels; 98 | handleLabelsUpdate(); 99 | } 100 | 101 | // Check if datasets are equals 102 | if (!isEqual(newData.datasets, chartInstance.value.data.datasets)) { 103 | newData.datasets.forEach((dataset, index) => { 104 | if (!isEmpty(dataset)) { 105 | const oldData = cloneDeep(chart.data); 106 | 107 | const oldDatasetKeys = Object.keys(oldData.datasets?.[index] ?? {}); 108 | const newDatasetKeys = Object.keys(dataset); 109 | 110 | // Get keys that aren't present in the new data 111 | const deletionKeys = oldDatasetKeys.filter((key) => { 112 | return key !== '_meta' && newDatasetKeys.indexOf(key) === -1; 113 | }); 114 | 115 | // Remove outdated key-value pairs 116 | deletionKeys.forEach((deletionKey) => { 117 | if (chart.data.datasets[index]) { 118 | delete chart.data.datasets[index][deletionKey as keyof ChartDataset]; 119 | } 120 | }); 121 | 122 | // Update attributes individually to avoid re-rendering the entire chart 123 | for (const attribute in dataset) { 124 | const attrValue = cloneDeep(dataset[attribute as keyof ChartDataset]); 125 | let datasetItem = chart.data.datasets[index] as any; 126 | if (!datasetItem) { 127 | chart.data.datasets[index] = {} as any; 128 | } 129 | if (dataset.hasOwnProperty(attribute) && attrValue != null && chart) { 130 | (chart.data.datasets[index] as any)[attribute] = attrValue; 131 | } 132 | } 133 | } else { 134 | chart.data.datasets = []; 135 | } 136 | }); 137 | } 138 | 139 | handleChartUpdate(); 140 | } else { 141 | if (chartInstance.value) { 142 | handleChartDestroy(); 143 | } 144 | renderChart(); 145 | } 146 | } 147 | 148 | function renderChart() { 149 | if (canvasRef.value) { 150 | chartInstance.value = new Chartjs.Chart(canvasRef.value as HTMLCanvasElement, { 151 | data: cloneDeep(props.chartData), 152 | type: chartType, 153 | options: cloneDeep(props.options) as ChartOptions, // Types won't work with props type 154 | plugins: props.plugins, 155 | }); 156 | handleChartRender(); 157 | } else { 158 | console.error( 159 | `Error on component ${componentName}, canvas cannot be rendered. Check if the render appends server-side` 160 | ); 161 | } 162 | } 163 | 164 | function handleLabelsUpdate() { 165 | emit('labels:update'); 166 | props.onLabelsUpdate && props.onLabelsUpdate(); 167 | } 168 | 169 | function handleChartRender() { 170 | if (chartInstance.value) { 171 | emit('chart:render', chartInstance.value); 172 | props.onChartRender && props.onChartRender(chartInstance.value); 173 | } 174 | } 175 | 176 | function handleChartUpdate() { 177 | if (chartInstance.value) { 178 | chartInstance.value.update(); 179 | emit('chart:update', chartInstance.value); 180 | props.onChartUpdate && props.onChartUpdate(chartInstance.value); 181 | } 182 | } 183 | 184 | function handleChartDestroy() { 185 | chartInstance.value && chartInstance.value.destroy(); 186 | emit('chart:destroy'); 187 | props.onChartDestroy && props.onChartDestroy(); 188 | } 189 | 190 | //- Hooks 191 | 192 | onMounted(renderChart); 193 | 194 | onBeforeUnmount(() => { 195 | if (chartInstance.value) { 196 | chartInstance.value.destroy(); 197 | } 198 | }); 199 | 200 | expose({ 201 | canvasRef, 202 | renderChart, 203 | chartInstance, 204 | canvasId, 205 | update: handleChartUpdate, 206 | } as const); 207 | 208 | return () => 209 | h( 210 | 'div', 211 | { 212 | style: { 213 | maxWidth: '100%', 214 | ...(props.styles as any), 215 | position: 'relative', 216 | }, 217 | class: props.cssClasses, 218 | }, 219 | [ 220 | h('canvas', { 221 | style: { 222 | maxWidth: '100%', 223 | maxHeight: '100%', 224 | }, 225 | id: canvasId, 226 | width: props.width, 227 | height: props.height, 228 | ref: canvasRef, 229 | }), 230 | ] 231 | ); 232 | }, 233 | }) as any; 234 | }; 235 | -------------------------------------------------------------------------------- /src/core/component.types.ts: -------------------------------------------------------------------------------- 1 | import { Chart, ChartData, ChartType, Plugin } from 'chart.js'; 2 | import { DefineComponent, PropType, Ref, ShallowRef } from 'vue'; 3 | import { StyleValue } from '../misc'; 4 | 5 | export type ComponentData = { 6 | /** Access to the canvas via computed template ref */ 7 | canvasRef: Ref; 8 | /** Force render the Chart */ 9 | renderChart: () => void; 10 | /** The complete chart instance */ 11 | chartInstance: ShallowRef | null>; 12 | /** The id of the Chart.js canvas element */ 13 | canvasId: string; 14 | /** Force update the Chart */ 15 | update: () => void; 16 | }; 17 | 18 | export type ChartComponentEmits = { 19 | 'labels:update': () => void; 20 | 'chart:update': (chartInstance: Chart) => void; 21 | 'chart:destroy': () => void; 22 | 'chart:render': (chartInstance: Chart) => void; 23 | }; 24 | 25 | export type ChartPropsOptions = { 26 | options: { type: PropType>; required: false }; 27 | chartId: { default: string; type: StringConstructor }; 28 | width: { default: 400; type: NumberConstructor }; 29 | height: { default: 400; type: NumberConstructor }; 30 | cssClasses: { type: StringConstructor; default: string }; 31 | styles: { type: PropType }; 32 | plugins: { type: PropType; default: () => any[] }; 33 | chartData: { type: PropType>; required: true }; 34 | onLabelsUpdate: { type: PropType<() => void> }; 35 | onChartUpdate: { type: PropType<(chartInstance: Chart) => void> }; 36 | onChartDestroy: { type: PropType<() => void> }; 37 | onChartRender: { type: PropType<(chartInstance: Chart) => void> }; 38 | }; 39 | 40 | export type ChartProps = { 41 | options?: Record; 42 | chartId?: string; 43 | width?: number; 44 | height?: number; 45 | cssClasses?: string; 46 | styles?: StyleValue; 47 | plugins?: Plugin[]; 48 | chartData?: ChartData; 49 | onLabelsUpdate?: () => void; 50 | onChartUpdate?: (chartInstance: Chart) => void; 51 | onChartDestroy?: () => void; 52 | onChartRender?: (chartInstance: Chart) => void; 53 | }; 54 | -------------------------------------------------------------------------------- /src/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component.builder'; 2 | export * from './component.types'; 3 | -------------------------------------------------------------------------------- /src/exports/component.exports.ts: -------------------------------------------------------------------------------- 1 | import { defineChartComponent } from '../core/component.builder'; 2 | 3 | /** 4 | * A bar chart provides a way of showing data values represented as vertical bars. It is sometimes used to show trend data, and the comparison of multiple data sets side by side. 5 | * 6 | * {@link - https://www.chartjs.org/docs/latest/charts/bar.html} 7 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 8 | */ 9 | export const BarChart = defineChartComponent('bar-chart', 'bar'); 10 | 11 | /** 12 | * Pie and doughnut charts are probably the most commonly used charts. They are divided into segments, the arc of each segment shows the proportional value of each piece of data. 13 | * 14 | * {@link - https://www.chartjs.org/docs/latest/charts/doughnut.html } 15 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 16 | */ 17 | export const DoughnutChart = defineChartComponent('doughnut-chart', 'doughnut'); 18 | 19 | /** 20 | * A line chart is a way of plotting data points on a line. Often, it is used to show trend data, or the comparison of two data sets. 21 | * 22 | * {@link - https://www.chartjs.org/docs/latest/charts/line.html } 23 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 24 | */ 25 | export const LineChart = defineChartComponent('line-chart', 'line'); 26 | 27 | /** 28 | * Pie and doughnut charts are probably the most commonly used charts. They are divided into segments, the arc of each segment shows the proportional value of each piece of data. 29 | * 30 | * {@link - https://www.chartjs.org/docs/latest/charts/doughnut.html#pie } 31 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 32 | */ 33 | export const PieChart = defineChartComponent('pie-chart', 'pie'); 34 | 35 | /** 36 | * Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value. 37 | * 38 | * {@link - https://www.chartjs.org/docs/latest/charts/polar.html } 39 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 40 | */ 41 | export const PolarAreaChart = defineChartComponent('polar-chart', 'polarArea'); 42 | 43 | /** 44 | * A radar chart is a way of showing multiple data points and the variation between them. 45 | * 46 | * {@link - https://www.chartjs.org/docs/latest/charts/radar.html } 47 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 48 | */ 49 | export const RadarChart = defineChartComponent('radar-chart', 'radar'); 50 | 51 | /** 52 | * A bubble chart is used to display three dimensions of data at the same time. The location of the bubble is determined by the first two dimensions and the corresponding horizontal and vertical axes. The third dimension is represented by the size of the individual bubbles. 53 | * 54 | * {@link - https://www.chartjs.org/docs/latest/charts/bubble.html } 55 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 56 | */ 57 | export const BubbleChart = defineChartComponent('bubble-chart', 'bubble'); 58 | 59 | /** 60 | * Scatter charts are based on basic line charts with the x axis changed to a linear axis. To use a scatter chart, data must be passed as objects containing X and Y properties. The example below creates a scatter chart with 4 points. 61 | * 62 | * {@link - https://www.chartjs.org/docs/latest/charts/scatter.html } 63 | * {@link - https://vue-chart-3.netlify.app/components/#list-of-all-components} 64 | */ 65 | export const ScatterChart = defineChartComponent('scatter-chart', 'scatter'); 66 | -------------------------------------------------------------------------------- /src/exports/hooks.exports.ts: -------------------------------------------------------------------------------- 1 | import { defineChartHook } from '../hooks'; 2 | 3 | /** 4 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 5 | * 6 | * ❗️ Still in beta, API can change in future updates 7 | */ 8 | export const useDoughnutChart = defineChartHook('doughnut'); 9 | 10 | /** 11 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 12 | * 13 | * ❗️ Still in beta, API can change in future updates 14 | */ 15 | export const useBarChart = defineChartHook('bar'); 16 | 17 | /** 18 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 19 | * 20 | * ❗️ Still in beta, API can change in future updates 21 | */ 22 | export const useLineChart = defineChartHook('line'); 23 | 24 | /** 25 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 26 | * 27 | * ❗️ Still in beta, API can change in future updates 28 | */ 29 | export const usePieChart = defineChartHook('pie'); 30 | 31 | /** 32 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 33 | * 34 | * ❗️ Still in beta, API can change in future updates 35 | */ 36 | export const usePolarAreaChart = defineChartHook('polarArea'); 37 | 38 | /** 39 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 40 | * 41 | * ❗️ Still in beta, API can change in future updates 42 | */ 43 | export const useRadarChart = defineChartHook('radar'); 44 | 45 | /** 46 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 47 | * 48 | * ❗️ Still in beta, API can change in future updates 49 | */ 50 | export const useBubbleChart = defineChartHook('bubble'); 51 | 52 | /** 53 | * {@link - https://vue-chart-3.netlify.app/components/hooks/#guide} 54 | * 55 | * ❗️ Still in beta, API can change in future updates 56 | */ 57 | export const useScatterChart = defineChartHook('scatter'); 58 | -------------------------------------------------------------------------------- /src/exports/index.ts: -------------------------------------------------------------------------------- 1 | export * from './component.exports'; 2 | export * from './hooks.exports'; 3 | -------------------------------------------------------------------------------- /src/hooks/hooks.builder.ts: -------------------------------------------------------------------------------- 1 | import { Chart, ChartData, ChartType, Plugin } from 'chart.js'; 2 | import { pascalCase } from '../utils'; 3 | import { computed, ref, unref } from 'vue'; 4 | import { VueChartComponent } from '.'; 5 | import type { StyleValue } from '../misc'; 6 | import { ExtractComponentData, MaybeRef } from '../utils'; 7 | import type { ChartHookReturnType } from './hooks.types'; 8 | 9 | export const defineChartHook = ( 10 | chartType: TType 11 | ) => { 12 | return (params: { 13 | chartData: MaybeRef>; 14 | options?: MaybeRef>; 15 | width?: number; 16 | height?: number; 17 | cssClasses?: string; 18 | styles?: StyleValue; 19 | plugins?: Plugin[]; 20 | onLabelsUpdate?: () => void; 21 | onChartUpdate?: (chartInstance: Chart) => void; 22 | onChartDestroy?: () => void; 23 | onChartRender?: (chartInstance: Chart) => void; 24 | /** Pass to true to return the correct jsx props */ 25 | jsx?: boolean; 26 | }): ChartHookReturnType => { 27 | const CHART_REF_NAME = `${chartType}ChartRef`; 28 | const _struct = { 29 | [CHART_REF_NAME]: ref>>(), 30 | }; 31 | const reactiveProps = computed(() => ({ 32 | ...params, 33 | ...(params.jsx && { 34 | ref: _struct[CHART_REF_NAME], 35 | }), 36 | ...(!params.jsx && { 37 | ref: CHART_REF_NAME, 38 | }), 39 | chartData: unref(params.chartData), 40 | options: unref(params.options), 41 | })); 42 | 43 | function update() { 44 | const chartComponentRef = _struct[CHART_REF_NAME].value; 45 | if (chartComponentRef) { 46 | chartComponentRef?.chartInstance.value?.update(); 47 | } else { 48 | console.warn(`No chartInstance to update (use${pascalCase(chartType)}Chart)`); 49 | } 50 | } 51 | 52 | return { 53 | [`${chartType}ChartProps`]: reactiveProps, 54 | [CHART_REF_NAME]: _struct[CHART_REF_NAME], 55 | update, 56 | }; 57 | }; 58 | }; 59 | -------------------------------------------------------------------------------- /src/hooks/hooks.types.ts: -------------------------------------------------------------------------------- 1 | import type { ChartType } from 'chart.js'; 2 | import type { 3 | ComponentPublicInstance, 4 | DefineComponent, 5 | Ref, 6 | ComputedOptions, 7 | MethodOptions, 8 | ComponentOptionsMixin, 9 | VNodeProps, 10 | AllowedComponentProps, 11 | ComponentCustomProps, 12 | } from 'vue'; 13 | import type { ChartComponentEmits, ChartPropsOptions, ComponentData } from '../core'; 14 | import { ExtractPropTypes } from '../utils'; 15 | 16 | export type VueChartComponent = DefineComponent< 17 | ChartPropsOptions, 18 | ComponentData, 19 | unknown, 20 | ComputedOptions, 21 | MethodOptions, 22 | ComponentOptionsMixin, 23 | ComponentOptionsMixin, 24 | ChartComponentEmits, 25 | string, 26 | PublicProps 27 | >; 28 | 29 | type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps; 30 | 31 | export interface HookOptions 32 | extends ChartPropsOptions { 33 | ref?: TJSX extends true ? Ref : string; 34 | } 35 | 36 | type DumbTypescript = 0; 37 | 38 | export type ChartHookReturnType = { 39 | [K in DumbTypescript as `${TType}ChartRef`]: Ref, 41 | ComponentData 42 | > | null>; 43 | } & { 44 | [K in DumbTypescript as `${TType}ChartProps`]: Ref>>; 45 | } & { 46 | update: () => void; 47 | }; 48 | -------------------------------------------------------------------------------- /src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './hooks.builder'; 2 | export * from './hooks.types'; 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { defineChartComponent } from './core'; 2 | export { defineChartHook } from './hooks'; 3 | export * from './exports'; 4 | 5 | export type { ExtractComponentData, ExtractComponentProps } from './utils'; 6 | -------------------------------------------------------------------------------- /src/misc/index.ts: -------------------------------------------------------------------------------- 1 | export * from './vue.types'; 2 | -------------------------------------------------------------------------------- /src/misc/vue.types.ts: -------------------------------------------------------------------------------- 1 | import { CSSProperties } from '@vue/runtime-dom'; 2 | 3 | export type VueInputEvent = Event & { target: HTMLInputElement }; 4 | 5 | export type StyleValue = string | CSSProperties | Array; 6 | export type VueHtmlClassParams = 7 | | string 8 | | Record 9 | | Array>; 10 | -------------------------------------------------------------------------------- /src/utils/format.utils.ts: -------------------------------------------------------------------------------- 1 | export function pascalCase(str: string): string { 2 | return (str.match(/[a-zA-Z0-9]+/g) || []) 3 | .map((w) => `${w.charAt(0).toUpperCase()}${w.slice(1)}`) 4 | .join(''); 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './types.utils'; 2 | export * from './format.utils'; 3 | -------------------------------------------------------------------------------- /src/utils/types.utils.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentPropsOptions } from '@vue/runtime-core'; 2 | import * as CSS from 'csstype'; 3 | import type { ComputedRef, DefineComponent, Prop, Ref } from 'vue'; 4 | 5 | export type StyleValue = string | CSS.Properties | Array; 6 | 7 | export type MaybeRef = T | Ref | ComputedRef; 8 | 9 | export type ExtractComponentProps = T extends DefineComponent< 10 | infer TProps, 11 | any, 12 | any, 13 | any, 14 | any, 15 | any, 16 | any, 17 | any 18 | > 19 | ? TProps extends ComponentPropsOptions 20 | ? ExtractPropTypes 21 | : TProps 22 | : never; 23 | 24 | export type ExtractComponentData = T extends DefineComponent< 25 | any, 26 | infer TData, 27 | any, 28 | any, 29 | any, 30 | any, 31 | any, 32 | any 33 | > 34 | ? TData 35 | : never; 36 | 37 | type RequiredKeys = { 38 | [K in keyof T]: T[K] extends 39 | | { 40 | required: true; 41 | } 42 | | { 43 | default: any; 44 | } 45 | | BooleanConstructor 46 | | { 47 | type: BooleanConstructor; 48 | } 49 | ? T[K] extends { 50 | default: undefined | (() => undefined); 51 | } 52 | ? never 53 | : K 54 | : never; 55 | }[keyof T]; 56 | 57 | type InferPropType = [T] extends [null] 58 | ? any 59 | : [T] extends [ 60 | { 61 | type: null | true; 62 | } 63 | ] 64 | ? any 65 | : [T] extends [ 66 | | ObjectConstructor 67 | | { 68 | type: ObjectConstructor; 69 | } 70 | ] 71 | ? Record 72 | : [T] extends [ 73 | | BooleanConstructor 74 | | { 75 | type: BooleanConstructor; 76 | } 77 | ] 78 | ? boolean 79 | : [T] extends [ 80 | | DateConstructor 81 | | { 82 | type: DateConstructor; 83 | } 84 | ] 85 | ? Date 86 | : [T] extends [ 87 | | (infer U)[] 88 | | { 89 | type: (infer U)[]; 90 | } 91 | ] 92 | ? U extends DateConstructor 93 | ? Date | InferPropType 94 | : InferPropType 95 | : [T] extends [Prop] 96 | ? unknown extends V 97 | ? D 98 | : V 99 | : T; 100 | 101 | type OptionalKeys = Exclude>; 102 | 103 | export type ExtractPropTypes = O extends object 104 | ? { 105 | [K in RequiredKeys]: InferPropType; 106 | } & { 107 | [K in OptionalKeys]?: InferPropType; 108 | } 109 | : { 110 | [K in string]: any; 111 | }; 112 | -------------------------------------------------------------------------------- /tests/setup.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'jest-canvas-mock/lib/window.js' { 2 | function getCanvasWindow(): any; 3 | export default getCanvasWindow; 4 | } 5 | -------------------------------------------------------------------------------- /tests/setup.ts: -------------------------------------------------------------------------------- 1 | import { vi } from 'vitest'; 2 | (global as any).jest = vi; 3 | 4 | // @ts-ignore 5 | import getCanvasWindow from 'jest-canvas-mock/lib/window'; 6 | 7 | const apis = [ 8 | 'Path2D', 9 | 'CanvasGradient', 10 | 'CanvasPattern', 11 | 'CanvasRenderingContext2D', 12 | 'DOMMatrix', 13 | 'ImageData', 14 | 'TextMetrics', 15 | 'ImageBitmap', 16 | 'createImageBitmap', 17 | ] as const; 18 | 19 | const canvasWindow = getCanvasWindow({ document: window.document }); 20 | 21 | apis.forEach((api) => { 22 | global[api] = canvasWindow[api]; 23 | global.window[api] = canvasWindow[api]; 24 | document.head.innerHTML = '
'; 25 | }); 26 | -------------------------------------------------------------------------------- /tests/unit/components/BarChart.spec.ts: -------------------------------------------------------------------------------- 1 | import { BarChart } from '../../../src'; 2 | import { setupComponentTest } from '../../utils/setup.utils'; 3 | 4 | describe('Bar chart renders and update correctly', async () => { 5 | setupComponentTest(BarChart, { 6 | labels: ['Paris', 'Nîmes', 'Toulon', 'Perpignan', 'Autre'], 7 | datasets: [ 8 | { 9 | data: [30, 40, 60, 70, 5], 10 | backgroundColor: ['#77CEFF', '#0079AF', '#123E6B', '#97B0C4', '#A5C8ED'], 11 | }, 12 | ], 13 | }); 14 | 15 | it('should be true', () => { 16 | expect(true).toBe(true); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/unit/vue3.spec.ts: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import * as Chartjs from 'chart.js/auto'; 3 | import { defineComponent, ref, computed, nextTick } from 'vue'; 4 | import { 5 | DoughnutChart, 6 | ExtractComponentData, 7 | ExtractComponentProps, 8 | BarChart, 9 | useBarChart, 10 | } from '../../src'; 11 | 12 | type TestExtractData = ExtractComponentData; 13 | let testAssignData: TestExtractData = {} as TestExtractData; 14 | const canvas: Chartjs.Chart<'doughnut'> | null = testAssignData?.chartInstance?.value; 15 | // Expect no type error 16 | 17 | type TestExtractProps = ExtractComponentProps; 18 | let testAssignProps: TestExtractProps = {} as TestExtractProps; 19 | const chartData: Chartjs.ChartData<'doughnut'> = testAssignProps?.chartData; 20 | // Expect no type error 21 | 22 | // @ts-expect-error 23 | const expectError: ChartData<'doughnut'> = testAssignProps?.blebleble; 24 | 25 | describe('Vue 3 - Doughnut chart', async () => { 26 | beforeEach(() => { 27 | vi.spyOn(console, 'error'); 28 | }); 29 | 30 | const dataset = [30, 40, 60, 70, 5]; 31 | 32 | const { vm } = mount(DoughnutChart, { 33 | props: { 34 | chartData: { 35 | labels: ['Paris', 'Nîmes', 'Toulon', 'Perpignan', 'Autre'], 36 | datasets: [ 37 | { 38 | data: dataset, 39 | backgroundColor: ['#77CEFF', '#0079AF', '#123E6B', '#97B0C4', '#A5C8ED'], 40 | }, 41 | ], 42 | }, 43 | options: { 44 | scales: { 45 | myScale: { 46 | type: 'logarithmic', 47 | position: 'right', 48 | }, 49 | }, 50 | plugins: { 51 | legend: { 52 | position: 'bottom', 53 | }, 54 | title: { 55 | display: true, 56 | text: 'Chart.js Doughnut Chart', 57 | }, 58 | }, 59 | }, 60 | }, 61 | }); 62 | await nextTick(); 63 | const canvas = vm.canvasRef; 64 | 65 | it('should have canvas registered', () => { 66 | expect(canvas).not.toBeNull(); 67 | expect(canvas).toBeDefined(); 68 | }); 69 | it('should have chartInstance variable instance of Chart.js', () => { 70 | expect(vm).toBeDefined(); 71 | expect(vm.chartInstance).toBeInstanceOf(Chartjs.Chart); 72 | }); 73 | it('should not have any console errors', () => { 74 | expect(console.error).not.toHaveBeenCalled(); 75 | }); 76 | 77 | // it('should have Chart constructed', async () => { 78 | // await timeout(3000); 79 | // var meta = vm.chartInstance?.getDatasetMeta(0)!; 80 | // console.log(meta); 81 | // expect(meta.type).toBe('doughnut'); 82 | // expect(meta.controller).not.toBe(undefined); 83 | // expect(meta.controller.index).toBe(0); 84 | // expect(meta.data).toEqual(dataset); 85 | 86 | // meta.controller.updateIndex(1); 87 | // expect(meta.controller.index).toBe(1); 88 | // }); 89 | }); 90 | 91 | const TestHooksComponent = defineComponent({ 92 | name: 'TestHooks', 93 | components: { 94 | BarChart, 95 | }, 96 | template: ` 97 |
98 | 99 |
100 | `, 101 | setup() { 102 | const data = ref([30, 40, 60, 70, 5]); 103 | const legendTop = ref(true); 104 | 105 | const options = computed(() => ({ 106 | scales: { 107 | y: { 108 | beginAtZero: true, 109 | }, 110 | }, 111 | })); 112 | 113 | const testData = computed(() => ({ 114 | labels: ['Paris', 'Nîmes', 'Toulon', 'Perpignan', 'Autre'], 115 | datasets: [ 116 | { 117 | data: data.value, 118 | backgroundColor: ['#77CEFF', '#0079AF', '#123E6B', '#97B0C4', '#A5C8ED'], 119 | }, 120 | ], 121 | })); 122 | 123 | const { barChartProps, barChartRef } = useBarChart({ 124 | chartData: testData, 125 | options: options, 126 | }); 127 | 128 | return { data, barChartProps, barChartRef }; 129 | }, 130 | }); 131 | 132 | describe('Vue 3 - with hooks', () => { 133 | beforeEach(() => { 134 | vi.spyOn(console, 'error'); 135 | }); 136 | 137 | const { vm } = mount(TestHooksComponent); 138 | 139 | const canvas = vm.$el.getElementsByTagName('canvas'); 140 | 141 | it('should have canvas registered', () => { 142 | expect(canvas).not.to.toBeNull(); 143 | expect(canvas).toBeDefined(); 144 | }); 145 | it('should have barChartRef variable instance of Vue', () => { 146 | expect(vm).toBeDefined(); 147 | expect(vm.barChartRef).toBeDefined(); 148 | }); 149 | it('should not have any console errors', () => { 150 | expect(console.error).not.toHaveBeenCalled(); 151 | }); 152 | }); 153 | -------------------------------------------------------------------------------- /tests/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './misc.utils'; 2 | -------------------------------------------------------------------------------- /tests/utils/misc.utils.ts: -------------------------------------------------------------------------------- 1 | export const timeout = (count: number) => new Promise((resolve) => setTimeout(resolve, count)); 2 | -------------------------------------------------------------------------------- /tests/utils/setup.utils.ts: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import { ChartData, ChartOptions, ChartType } from 'chart.js/auto'; 3 | import { 4 | ComponentOptionsMixin, 5 | ComputedOptions, 6 | DefineComponent, 7 | MethodOptions, 8 | nextTick, 9 | } from 'vue'; 10 | import { ChartComponentEmits, ChartPropsOptions, ComponentData } from '../../src/core'; 11 | 12 | const commonOptions: ChartOptions = { 13 | scales: { 14 | myScale: { 15 | type: 'logarithmic', 16 | position: 'right', 17 | }, 18 | }, 19 | plugins: { 20 | legend: { 21 | position: 'bottom', 22 | }, 23 | title: { 24 | display: true, 25 | text: 'Testing vue-chart-3', 26 | }, 27 | }, 28 | }; 29 | 30 | export async function setupComponentTest< 31 | V extends DefineComponent< 32 | ChartPropsOptions, 33 | ComponentData, 34 | unknown, 35 | ComputedOptions, 36 | MethodOptions, 37 | ComponentOptionsMixin, 38 | ComponentOptionsMixin, 39 | ChartComponentEmits 40 | >, 41 | C extends ChartType = V extends DefineComponent< 42 | ChartPropsOptions, 43 | any, 44 | any, 45 | any, 46 | any, 47 | any, 48 | any, 49 | any 50 | > 51 | ? V 52 | : any 53 | >(component: V, chartData: ChartData) { 54 | beforeEach(() => { 55 | vi.spyOn(console, 'error'); 56 | }); 57 | 58 | const wrapper = mount(component as any, { 59 | props: { 60 | chartData, 61 | options: commonOptions, 62 | }, 63 | }); 64 | 65 | await nextTick(); 66 | 67 | return wrapper; 68 | } 69 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["tests/**/*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "allowSyntheticDefaultImports": true, 7 | "esModuleInterop": true, 8 | "removeComments": true, 9 | "noImplicitAny": true, 10 | "noUnusedLocals": false, 11 | "strictNullChecks": true, 12 | "strict": true, 13 | "checkJs": false, 14 | "pretty": true, 15 | "sourceMap": true, 16 | "downlevelIteration": true, 17 | "noEmit": true, 18 | "skipLibCheck": true, 19 | "types": ["vitest/globals"] 20 | }, 21 | "include": ["./src/**/*.ts", "./tests/**/*.ts"], 22 | "exclude": ["node_modules"] 23 | } 24 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: true, 7 | clean: true, 8 | external: ['chart.js', 'lodash-es'], 9 | }); 10 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { defineConfig } from 'vite'; 3 | 4 | export default defineConfig({ 5 | test: { 6 | globals: true, 7 | environment: 'jsdom', 8 | setupFiles: ['./tests/setup.ts'], 9 | }, 10 | }); 11 | --------------------------------------------------------------------------------