├── .clean-publish
├── .commitlintrc.json
├── .czrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .nano-staged.json
├── .npmrc
├── .nvmrc
├── .prettierrc
├── .simple-git-hooks.json
├── .size-limit.json
├── CHANGELOG.md
├── LICENSE
├── LICENSE.md
├── README.md
├── netlify.toml
├── package.json
├── pnpm-lock.yaml
├── rollup.config.js
├── sandboxes
├── bar
│ ├── grouped
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ ├── horizontal
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ ├── stacked
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ └── vertical
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── bubble
│ └── default
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── chart
│ ├── canvas
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ ├── events
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ ├── multitype
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ └── ref
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── doughnut
│ └── default
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── line
│ ├── area
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ ├── default
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
│ └── multiaxis
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── pie
│ └── default
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── polarArea
│ └── default
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── radar
│ └── default
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
├── scatter
│ └── default
│ │ ├── App.tsx
│ │ ├── index.html
│ │ ├── index.tsx
│ │ ├── package.json
│ │ └── vite.config.js
└── tsconfig.json
├── src
├── chart.tsx
├── index.ts
├── typedCharts.tsx
├── types.ts
└── utils.ts
├── stories
├── Bar.tsx
├── Bubble.tsx
├── Chart.data.ts
├── Chart.tsx
├── Doughnut.tsx
├── Line.tsx
├── Pie.tsx
├── PolarArea.tsx
├── Radar.tsx
├── Scatter.tsx
└── data.ts
├── test
├── .eslintrc.json
├── chart.test-d.tsx
├── chart.test.tsx
└── setup.js
├── tsconfig.json
├── vite.config.js
└── website
├── .gitignore
├── CNAME
├── README.md
├── babel.config.js
├── docs
├── chartjs-v2.mdx
├── chartjs-v3.mdx
├── components
│ ├── bar.mdx
│ ├── bubble.mdx
│ ├── chart.mdx
│ ├── docs.js
│ ├── doughnut.mdx
│ ├── index.mdx
│ ├── line.mdx
│ ├── pie.mdx
│ ├── polar-area.mdx
│ ├── radar.mdx
│ └── scatter.mdx
├── docs.js
├── examples
│ ├── area-chart.mdx
│ ├── bubble-chart.mdx
│ ├── chart-events.mdx
│ ├── chart-ref.mdx
│ ├── docs.js
│ ├── doughnut-chart.mdx
│ ├── gradient-chart.mdx
│ ├── grouped-bar-chart.mdx
│ ├── horizontal-bar-chart.mdx
│ ├── index.mdx
│ ├── line-chart.mdx
│ ├── multiaxis-line-chart.mdx
│ ├── multitype-chart.mdx
│ ├── pie-chart.mdx
│ ├── polar-area-chart.mdx
│ ├── radar-chart.mdx
│ ├── scatter-chart.mdx
│ ├── stacked-bar-chart.mdx
│ └── vertical-bar-chart.mdx
├── faq
│ ├── canvas-context.md
│ ├── chartjs-instance.md
│ ├── docs.js
│ ├── esm-only.md
│ ├── fill-property.md
│ ├── index.mdx
│ ├── maintain-aspect-ratio.md
│ ├── registered-element.md
│ ├── registered-scale.md
│ ├── typescript.md
│ └── why-two.md
├── index.mdx
├── migration-to-v4.md
├── migration-to-v5.md
├── working-with-datasets.md
└── working-with-events.md
├── docusaurus.config.js
├── package.json
├── pnpm-lock.yaml
├── sidebars.js
├── src
├── components
│ ├── ContextProvider.tsx
│ └── PropsTable.tsx
└── css
│ └── custom.css
├── static
├── .nojekyll
└── img
│ ├── favicon.ico
│ └── logo.svg
└── tsconfig.json
/.clean-publish:
--------------------------------------------------------------------------------
1 | {
2 | "withoutPublish": true,
3 | "tempDir": "package",
4 | "fields": ["tsd"],
5 | "files": ["website"]
6 | }
7 |
--------------------------------------------------------------------------------
/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@commitlint/config-conventional"],
3 | "rules": {
4 | "body-max-line-length": [0]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.czrc:
--------------------------------------------------------------------------------
1 | {
2 | "path": "@commitlint/cz-commitlint"
3 | }
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs
2 | # editorconfig.org
3 | root = true
4 |
5 | [*]
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 | indent_style = space
11 | indent_size = 2
12 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | .publish/*
2 | dist/*
3 | lib/*
4 | node_modules/*
5 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "plugins": ["@typescript-eslint"],
4 | "extends": [
5 | "standard",
6 | "standard-react",
7 | "plugin:prettier/recommended",
8 | "plugin:@typescript-eslint/recommended"
9 | ],
10 | "env": {
11 | "browser": true
12 | },
13 | "parserOptions": {
14 | "ecmaVersion": "latest",
15 | "ecmaFeatures": {
16 | "jsx": true
17 | }
18 | },
19 | "settings": {
20 | "react": {
21 | "version": "detect"
22 | }
23 | },
24 | "rules": {
25 | "curly": [2, "multi-line"],
26 | "quotes": [2, "single", "avoid-escape"],
27 | "react/display-name": 0,
28 | "react/jsx-boolean-value": 1,
29 | "jsx-quotes": [1, "prefer-single"],
30 | "react/jsx-no-undef": 1,
31 | "react/jsx-sort-props": 0,
32 | "react/jsx-uses-react": 1,
33 | "react/jsx-uses-vars": 1,
34 | "react/no-did-mount-set-state": 1,
35 | "react/no-did-update-set-state": 1,
36 | "react/no-unknown-property": 1,
37 | "react/prop-types": 0,
38 | "react/react-in-jsx-scope": 1,
39 | "react/self-closing-comp": 1,
40 | "semi": [2, "always"],
41 | "strict": 0,
42 | "no-use-before-define": 0,
43 | "@typescript-eslint/no-use-before-define": 2
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # builds
7 | package
8 | dist
9 | storybook-static
10 |
11 | # misc
12 | .DS_Store
13 | .env
14 | .env.*
15 |
16 | npm-debug.log*
17 |
18 | # testing
19 | coverage
20 |
--------------------------------------------------------------------------------
/.nano-staged.json:
--------------------------------------------------------------------------------
1 | {
2 | "**/*.{js,ts,tsx}": ["prettier --write", "eslint"]
3 | }
4 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | strict-peer-dependencies=false
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/*
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "jsxSingleQuote": true,
4 | "semi": true,
5 | "tabWidth": 2,
6 | "bracketSpacing": true,
7 | "arrowParens": "avoid",
8 | "trailingComma": "es5"
9 | }
10 |
--------------------------------------------------------------------------------
/.simple-git-hooks.json:
--------------------------------------------------------------------------------
1 | {
2 | "commit-msg": "pnpm commitlint --edit \"$1\"",
3 | "pre-commit": "pnpm nano-staged",
4 | "pre-push": "pnpm test"
5 | }
6 |
--------------------------------------------------------------------------------
/.size-limit.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "path": "dist/index.js",
4 | "limit": "1.6 KB",
5 | "webpack": false,
6 | "running": false
7 | },
8 | {
9 | "path": "dist/index.js",
10 | "limit": "800 B",
11 | "import": "{ Chart }"
12 | }
13 | ]
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ## [5.2.0](https://github.com/reactchartjs/react-chartjs-2/compare/v5.1.0...v5.2.0) (2023-01-09)
6 |
7 |
8 | ### Features
9 |
10 | * restore compatability with webpack 4 ([#1146](https://github.com/reactchartjs/react-chartjs-2/issues/1146)) ([082c26d](https://github.com/reactchartjs/react-chartjs-2/commit/082c26d559f210af7c55c31a826fe4821a429700))
11 |
12 | ## [5.1.0](https://github.com/reactchartjs/react-chartjs-2/compare/v5.0.1...v5.1.0) (2022-12-19)
13 |
14 |
15 | ### Features
16 |
17 | * restore CommonJS bundle ([#1137](https://github.com/reactchartjs/react-chartjs-2/issues/1137)) ([7db2643](https://github.com/reactchartjs/react-chartjs-2/commit/7db264337200c999bc987e0e288df08ef7813ee3))
18 |
19 | ### [5.0.1](https://github.com/reactchartjs/react-chartjs-2/compare/v5.0.0...v5.0.1) (2022-11-17)
20 |
21 |
22 | ### Bug Fixes
23 |
24 | * remove chart.js v3 from peer dependencies ([7ae5702](https://github.com/reactchartjs/react-chartjs-2/commit/7ae57023783f4c64210119f0447bd1c0e1ba92e9))
25 |
26 | ## [5.0.0](https://github.com/reactchartjs/react-chartjs-2/compare/v4.3.1...v5.0.0) (2022-11-17)
27 |
28 |
29 | ### ⚠ BREAKING CHANGES
30 |
31 | * no commonjs support
32 |
33 | ### Features
34 |
35 | * chart.js v4 support ([#1109](https://github.com/reactchartjs/react-chartjs-2/issues/1109)) ([deb2110](https://github.com/reactchartjs/react-chartjs-2/commit/deb211084757225e3ddb2574b567e805ba7eeeb6))
36 | * package type module ([#1108](https://github.com/reactchartjs/react-chartjs-2/issues/1108)) ([6eb8ce7](https://github.com/reactchartjs/react-chartjs-2/commit/6eb8ce7f23654e46d17aedc104375112b2f2a955))
37 |
38 |
39 | ### Bug Fixes
40 |
41 | * **deps:** update dependency chart.js to v4 ([#1104](https://github.com/reactchartjs/react-chartjs-2/issues/1104)) ([6192408](https://github.com/reactchartjs/react-chartjs-2/commit/61924087de28a7ee0bba6f61c50a0bde362b662c))
42 | * **deps:** update dependency react-scripts to v5.0.1 ([#1049](https://github.com/reactchartjs/react-chartjs-2/issues/1049)) ([38a9796](https://github.com/reactchartjs/react-chartjs-2/commit/38a9796f1cefa63390d4eaf3eec960c77fe78d34))
43 | * **deps:** update react monorepo to v18 ([#1031](https://github.com/reactchartjs/react-chartjs-2/issues/1031)) ([ad73425](https://github.com/reactchartjs/react-chartjs-2/commit/ad734256e173353222995b4edfbf7a8ad0dc96f3))
44 | * **deps:** update react monorepo to v18.2.0 ([#1082](https://github.com/reactchartjs/react-chartjs-2/issues/1082)) ([72e7352](https://github.com/reactchartjs/react-chartjs-2/commit/72e7352fcdff182465bfdcd6a7f6c4579d062d01))
45 | * **site:** [#1076](https://github.com/reactchartjs/react-chartjs-2/issues/1076) expand the docusaurus container content to give the sandboxes more space ([#1077](https://github.com/reactchartjs/react-chartjs-2/issues/1077)) ([b512e8d](https://github.com/reactchartjs/react-chartjs-2/commit/b512e8dc130e28c1284be77d4ef6c3a788b9e262))
46 |
47 | ### [4.3.1](https://github.com/reactchartjs/react-chartjs-2/compare/v4.3.0...v4.3.1) (2022-07-13)
48 |
49 |
50 | ### Bug Fixes
51 |
52 | * update options without resetting chart ([#1061](https://github.com/reactchartjs/react-chartjs-2/issues/1061)) ([fa0a4bb](https://github.com/reactchartjs/react-chartjs-2/commit/fa0a4bbdb3d85735db289494c4bdf1da083a51da))
53 |
54 | ## [4.3.0](https://github.com/reactchartjs/react-chartjs-2/compare/v4.2.0...v4.3.0) (2022-07-12)
55 |
56 |
57 | ### Features
58 |
59 | * assure redraw occurs when type changes ([#1054](https://github.com/reactchartjs/react-chartjs-2/issues/1054)) ([#1055](https://github.com/reactchartjs/react-chartjs-2/issues/1055)) ([bf0538f](https://github.com/reactchartjs/react-chartjs-2/commit/bf0538fd953ee878659d0b5647676fbfda460c76))
60 |
61 | ## [4.2.0](https://github.com/reactchartjs/react-chartjs-2/compare/v4.1.0...v4.2.0) (2022-06-07)
62 |
63 |
64 | ### Features
65 |
66 | * implement passing updateMode property to chart's update method ([#1043](https://github.com/reactchartjs/react-chartjs-2/issues/1043)) ([96d2714](https://github.com/reactchartjs/react-chartjs-2/commit/96d2714c3df88346152a1b66b8fe729d43151e40))
67 |
68 | ## [4.1.0](https://github.com/reactchartjs/react-chartjs-2/compare/v4.0.1...v4.1.0) (2022-04-07)
69 |
70 |
71 | ### Features
72 |
73 | * react 18 support ([#1034](https://github.com/reactchartjs/react-chartjs-2/issues/1034)) ([058035a](https://github.com/reactchartjs/react-chartjs-2/commit/058035a3e2da17ad9ee0c9f50793da3aaefb3913))
74 |
75 | ### [4.0.1](https://github.com/reactchartjs/react-chartjs-2/compare/v4.0.0...v4.0.1) (2022-01-19)
76 |
77 |
78 | ### Bug Fixes
79 |
80 | * compatability with react 16 typings ([#987](https://github.com/reactchartjs/react-chartjs-2/issues/987)) ([4a01054](https://github.com/reactchartjs/react-chartjs-2/commit/4a010540ac01b1e4b299705ddd93f412df4875d1)), closes [#870](https://github.com/reactchartjs/react-chartjs-2/issues/870)
81 | * **deps:** update dependency @svgr/webpack to v6 ([#999](https://github.com/reactchartjs/react-chartjs-2/issues/999)) ([7611ebd](https://github.com/reactchartjs/react-chartjs-2/commit/7611ebdbdbf4e91991b1a15d393fbadf2de01246))
82 | * **deps:** update dependency react-scripts to v5 ([#1001](https://github.com/reactchartjs/react-chartjs-2/issues/1001)) ([3936227](https://github.com/reactchartjs/react-chartjs-2/commit/3936227b4e6865bbd20419af4a5b0b49561f608c))
83 | * **deps:** update docusaurus monorepo to v2.0.0-beta.14 ([#994](https://github.com/reactchartjs/react-chartjs-2/issues/994)) ([2a24ee9](https://github.com/reactchartjs/react-chartjs-2/commit/2a24ee92203c703d16c3784eccb0011b5b870802))
84 |
85 | ## [4.0.0](https://github.com/reactchartjs/react-chartjs-2/compare/v3.3.0...v4.0.0) (2021-11-22)
86 |
87 |
88 | ### ⚠ BREAKING CHANGES
89 |
90 | * getDatasetAtEvent, getElementAtEvent and getElementsAtEvent props are removed,
91 | utils with the same names can used instead
92 | * New target browsers: ie 11 dropped for regular bundle, modern bundle builds for
93 | browsers with es6 modules support.
94 | * Functional data prop is removed
95 | * Added support of tree-shaking of Chart.js. Now you should register Chart.js
96 | components by yourself.
97 | * default export is renamed to Chart
98 | * Chart.js re-exports are removed
99 |
100 | ### Features
101 |
102 | * datasetIdKey prop ([#848](https://github.com/reactchartjs/react-chartjs-2/issues/848)) ([f895766](https://github.com/reactchartjs/react-chartjs-2/commit/f895766f012c0d3781d75b5f83adc6dbc8de0b03))
103 |
104 |
105 | * default export is renamed to Chart ([#836](https://github.com/reactchartjs/react-chartjs-2/issues/836)) ([131daa0](https://github.com/reactchartjs/react-chartjs-2/commit/131daa008d3a3c280ba9e751c67ca926708b60e4))
106 | * functional data prop is removed ([#840](https://github.com/reactchartjs/react-chartjs-2/issues/840)) ([b64dfb0](https://github.com/reactchartjs/react-chartjs-2/commit/b64dfb0430bf5817a5f8b8708551934ad426921e))
107 | * getDatasetAtEvent, getElementAtEvent and getElementsAtEvent props are removed ([#845](https://github.com/reactchartjs/react-chartjs-2/issues/845)) ([6a9b2a7](https://github.com/reactchartjs/react-chartjs-2/commit/6a9b2a7527d23e7409c9273ad32eb100122ffb51))
108 | * new target browsers ([#841](https://github.com/reactchartjs/react-chartjs-2/issues/841)) ([b1e83db](https://github.com/reactchartjs/react-chartjs-2/commit/b1e83db599e7f9b832c2fe1942b5e5f296730dd9))
109 | * removed chart.js re-exports ([#835](https://github.com/reactchartjs/react-chartjs-2/issues/835)) ([30d5c2d](https://github.com/reactchartjs/react-chartjs-2/commit/30d5c2d457eae0b1142ea4ffb6eff8f583b60817))
110 | * tree-shaking ([#839](https://github.com/reactchartjs/react-chartjs-2/issues/839)) ([fcd2849](https://github.com/reactchartjs/react-chartjs-2/commit/fcd2849037bb01d2eeadbfbc90c90054eb620d4c))
111 |
112 | ## [3.3.0](https://github.com/reactchartjs/react-chartjs-2/compare/v3.2.0...v3.3.0) (2021-10-26)
113 |
114 |
115 | ### Features
116 |
117 | * export chart props types ([#810](https://github.com/reactchartjs/react-chartjs-2/issues/810)) ([82ab334](https://github.com/reactchartjs/react-chartjs-2/commit/82ab334c62939fb4924ed6021502fccfea29a5a2)), closes [#720](https://github.com/reactchartjs/react-chartjs-2/issues/720)
118 |
119 |
120 | ### Bug Fixes
121 |
122 | * data updating fix ([#807](https://github.com/reactchartjs/react-chartjs-2/issues/807)) ([45a50cc](https://github.com/reactchartjs/react-chartjs-2/commit/45a50cc46196ce64088a463b6f3b384a6c98eb06)), closes [#806](https://github.com/reactchartjs/react-chartjs-2/issues/806)
123 |
124 | ## [3.2.0](https://github.com/reactchartjs/react-chartjs-2/compare/v3.1.1...v3.2.0) (2021-10-21)
125 |
126 |
127 | ### Features
128 |
129 | * remove lodash ([#784](https://github.com/reactchartjs/react-chartjs-2/issues/784)) ([5594170](https://github.com/reactchartjs/react-chartjs-2/commit/559417024ef2fb34005727ff16d8fae8615cb071))
130 |
131 |
132 | ### Bug Fixes
133 |
134 | * improve and fix rerendering ([#790](https://github.com/reactchartjs/react-chartjs-2/issues/790)) ([330fb1c](https://github.com/reactchartjs/react-chartjs-2/commit/330fb1cf0913bdbacda5ef755fb58c79482e1ea2))
135 | * multitype chart typings ([#792](https://github.com/reactchartjs/react-chartjs-2/issues/792)) ([2f19eb3](https://github.com/reactchartjs/react-chartjs-2/commit/2f19eb3eba9681f383ca23e7a3a1f1c581c89061))
136 |
137 | ### [3.1.1](https://github.com/reactchartjs/react-chartjs-2/compare/v3.1.0...v3.1.1) (2021-10-19)
138 |
139 |
140 | ### Bug Fixes
141 |
142 | * components' props types ([#782](https://github.com/reactchartjs/react-chartjs-2/issues/782)) ([eba8a27](https://github.com/reactchartjs/react-chartjs-2/commit/eba8a2794bb802dacc395a450110af8765fea868)), closes [#734](https://github.com/reactchartjs/react-chartjs-2/issues/734) [#741](https://github.com/reactchartjs/react-chartjs-2/issues/741)
143 |
144 | ## [3.1.0](https://github.com/reactchartjs/react-chartjs-2/compare/v2.4.0...v3.1.0) (2021-10-17)
145 |
146 |
147 | ### Features
148 |
149 | * Reduced package size
150 |
151 |
152 | ### Bug Fixes
153 |
154 | * minor types fixes ([#759](https://github.com/reactchartjs/react-chartjs-2/issues/759)) ([fe6c00f](https://github.com/reactchartjs/react-chartjs-2/commit/fe6c00f05cdc3099a66a7ac0c05fb5e6f216209a))
155 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2020 Jeremy Ayerst
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Jeremy Ayerst
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 | # react-chartjs-2
2 |
3 |
4 |
5 | React components for Chart.js, the most popular charting library.
6 |
7 | Supports Chart.js v4 and v3.
8 |
9 | [![NPM version][npm]][npm-url]
10 | [![Downloads][downloads]][downloads-url]
11 | [![Build status][build]][build-url]
12 | [![Coverage status][coverage]][coverage-url]
13 | [![Bundle size][size]][size-url]
14 |
15 | [npm]: https://img.shields.io/npm/v/react-chartjs-2.svg
16 | [npm-url]: https://www.npmjs.com/package/react-chartjs-2
17 |
18 | [downloads]: https://img.shields.io/npm/dm/react-chartjs-2.svg
19 | [downloads-url]: https://www.npmjs.com/package/react-chartjs-2
20 |
21 | [build]: https://img.shields.io/github/actions/workflow/status/reactchartjs/react-chartjs-2/ci.yml?branch=master
22 | [build-url]: https://github.com/reactchartjs/react-chartjs-2/actions
23 |
24 | [coverage]: https://img.shields.io/codecov/c/github/reactchartjs/react-chartjs-2.svg
25 | [coverage-url]: https://app.codecov.io/gh/reactchartjs/react-chartjs-2
26 |
27 | [size]: https://img.shields.io/bundlephobia/minzip/react-chartjs-2
28 | [size-url]: https://bundlephobia.com/package/react-chartjs-2
29 |
30 |
31 | Quickstart
32 | •
33 | Docs
34 | •
35 | Slack
36 | •
37 | Stack Overflow
38 |
39 |
40 |
41 | ## Quickstart
42 |
43 | Install this library with peer dependencies:
44 |
45 | ```bash
46 | pnpm add react-chartjs-2 chart.js
47 | # or
48 | yarn add react-chartjs-2 chart.js
49 | # or
50 | npm i react-chartjs-2 chart.js
51 | ```
52 |
53 | We recommend using `chart.js@^4.0.0`.
54 |
55 | Then, import and use individual components:
56 |
57 | ```jsx
58 | import { Doughnut } from 'react-chartjs-2';
59 |
60 |
61 | ```
62 |
63 | Need an API to fetch data? Consider [Cube](https://cube.dev/?ref=eco-react-chartjs), an open-source API for data apps.
64 |
65 |
66 |
67 | [](https://cube.dev/?ref=eco-react-chartjs)
68 |
69 | ## Docs
70 |
71 | - [Migration to v4](https://react-chartjs-2.js.org/docs/migration-to-v4)
72 | - [Working with datasets](https://react-chartjs-2.js.org/docs/working-with-datasets)
73 | - [Working with events](https://react-chartjs-2.js.org/docs/working-with-events)
74 | - [FAQ](https://react-chartjs-2.js.org/faq)
75 | - [Components](https://react-chartjs-2.js.org/components)
76 | - [Examples](https://react-chartjs-2.js.org/examples)
77 |
78 | ## License
79 |
80 | [MIT Licensed](LICENSE)
81 | Copyright (c) 2020 Jeremy Ayerst
82 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build.environment]
2 | NPM_FLAGS = "--version" # prevent Netlify npm install
3 | [build]
4 | publish = "website/build"
5 | command = "npx pnpm i --store=node_modules/.pnpm-store && cd website && npx pnpm i --store=node_modules/.pnpm-store && npx pnpm build"
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-chartjs-2",
3 | "type": "module",
4 | "version": "5.2.0",
5 | "description": "React components for Chart.js",
6 | "author": "Jeremy Ayerst",
7 | "homepage": "https://github.com/reactchartjs/react-chartjs-2",
8 | "license": "MIT",
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/reactchartjs/react-chartjs-2.git"
12 | },
13 | "bugs": {
14 | "url": "https://github.com/reactchartjs/react-chartjs-2/issues"
15 | },
16 | "keywords": [
17 | "chart",
18 | "chart-js",
19 | "chart.js",
20 | "react-chartjs-2",
21 | "react chart.js",
22 | "react-chart.js"
23 | ],
24 | "sideEffects": false,
25 | "types": "./dist/index.d.ts",
26 | "exports": "./src/index.ts",
27 | "publishConfig": {
28 | "main": "./dist/index.cjs",
29 | "module": "./dist/index.js",
30 | "exports": {
31 | "types": "./dist/index.d.ts",
32 | "import": "./dist/index.js",
33 | "require": "./dist/index.cjs"
34 | },
35 | "directory": "package"
36 | },
37 | "files": [
38 | "dist"
39 | ],
40 | "scripts": {
41 | "prepublishOnly": "pnpm test && pnpm build && del ./package && clean-publish",
42 | "postpublish": "del ./package",
43 | "emitDeclarations": "tsc --emitDeclarationOnly",
44 | "build": "rollup -c && pnpm emitDeclarations",
45 | "start:storybook": "start-storybook -p 6006 --ci",
46 | "build:storybook": "del ./storybook-static; NODE_ENV=production build-storybook",
47 | "test:lint": "eslint \"src/**/*.{ts,tsx}\" \"stories/**/*.{ts,tsx}\" \"sandboxes/**/*.{ts,tsx}\" \"test/**/*.{ts,tsx}\"",
48 | "test:unit": "vitest run --coverage",
49 | "test:unit:watch": "vitest watch",
50 | "test:size": "size-limit",
51 | "test:typings": "tsd",
52 | "test": "pnpm test:lint && pnpm test:unit",
53 | "format": "prettier --write src",
54 | "commit": "cz",
55 | "bumpVersion": "standard-version",
56 | "createGithubRelease": "simple-github-release",
57 | "release": "pnpm bumpVersion && git push origin master --tags && pnpm createGithubRelease",
58 | "updateGitHooks": "simple-git-hooks"
59 | },
60 | "peerDependencies": {
61 | "chart.js": "^4.1.1",
62 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
63 | },
64 | "devDependencies": {
65 | "@commitlint/cli": "^17.0.0",
66 | "@commitlint/config-conventional": "^17.0.0",
67 | "@commitlint/cz-commitlint": "^17.0.0",
68 | "@rollup/plugin-node-resolve": "^15.0.1",
69 | "@size-limit/preset-big-lib": "^8.0.0",
70 | "@storybook/addon-actions": "^6.3.12",
71 | "@storybook/addon-controls": "^6.3.12",
72 | "@storybook/addon-docs": "^6.3.12",
73 | "@storybook/addons": "^6.3.12",
74 | "@storybook/builder-vite": "^0.2.5",
75 | "@storybook/client-api": "^6.5.13",
76 | "@storybook/client-logger": "^6.5.13",
77 | "@storybook/react": "^6.3.12",
78 | "@swc/core": "^1.3.17",
79 | "@swc/helpers": "^0.4.0",
80 | "@testing-library/jest-dom": "^5.5.0",
81 | "@testing-library/react": "^13.0.0",
82 | "@types/faker": "^5.5.8",
83 | "@types/node": "^18.0.0",
84 | "@types/react": "^18.0.0",
85 | "@types/react-dom": "^18.0.0",
86 | "@types/testing-library__jest-dom": "^5.14.5",
87 | "@typescript-eslint/eslint-plugin": "^5.0.0",
88 | "@typescript-eslint/parser": "^5.0.0",
89 | "@vitejs/plugin-react": "^3.0.0",
90 | "@vitest/coverage-c8": "^0.27.0",
91 | "browserslist": "^4.17.3",
92 | "chart.js": "^4.1.1",
93 | "chartjs-adapter-date-fns": "^3.0.0",
94 | "chartjs-plugin-annotation": "^2.0.1",
95 | "chartjs-plugin-zoom": "^2.0.0",
96 | "clean-publish": "^4.0.0",
97 | "commitizen": "^4.2.4",
98 | "date-fns": "^2.25.0",
99 | "del-cli": "^5.0.0",
100 | "eslint": "^7.32.0",
101 | "eslint-config-prettier": "^8.3.0",
102 | "eslint-config-standard": "^16.0.3",
103 | "eslint-config-standard-react": "^12.0.0",
104 | "eslint-plugin-import": "^2.25.1",
105 | "eslint-plugin-node": "^11.0.0",
106 | "eslint-plugin-prettier": "^4.0.0",
107 | "eslint-plugin-promise": "^5.1.0",
108 | "eslint-plugin-react": "^7.17.0",
109 | "faker": "^5.5.3",
110 | "jsdom": "^21.0.0",
111 | "nano-staged": "^0.8.0",
112 | "prettier": "^2.0.4",
113 | "react": "^18.0.0",
114 | "react-dom": "^18.0.0",
115 | "react-test-renderer": "^18.0.0",
116 | "rollup": "^3.3.0",
117 | "rollup-plugin-swc3": "^0.8.0",
118 | "simple-git-hooks": "^2.6.1",
119 | "simple-github-release": "^1.0.0",
120 | "size-limit": "^8.0.0",
121 | "standard-version": "^9.3.1",
122 | "tsd": "^0.25.0",
123 | "typescript": "^4.9.4",
124 | "vite": "^4.0.0",
125 | "vitest": "^0.27.0",
126 | "vitest-canvas-mock": "^0.2.1"
127 | },
128 | "tsd": {
129 | "directory": "./test",
130 | "compilerOptions": {
131 | "paths": {
132 | "react-chartjs-2": [
133 | "./src"
134 | ]
135 | }
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { swc } from 'rollup-plugin-swc3';
2 | import { nodeResolve } from '@rollup/plugin-node-resolve';
3 | import pkg from './package.json' assert { type: 'json' };
4 |
5 | const extensions = ['.js', '.ts', '.tsx'];
6 | const external = _ => /node_modules/.test(_) && !/@swc\/helpers/.test(_);
7 | const plugins = targets => [
8 | nodeResolve({
9 | extensions,
10 | }),
11 | swc({
12 | tsconfig: false,
13 | jsc: {
14 | parser: {
15 | syntax: 'typescript',
16 | tsx: true,
17 | },
18 | transform: {
19 | react: {
20 | useBuiltins: true,
21 | },
22 | },
23 | externalHelpers: true,
24 | },
25 | env: {
26 | targets,
27 | },
28 | module: {
29 | type: 'es6',
30 | },
31 | sourceMaps: true,
32 | }),
33 | ];
34 |
35 | export default {
36 | input: pkg.exports,
37 | plugins: plugins('defaults and supports es6-module'),
38 | external,
39 | output: [
40 | {
41 | file: pkg.publishConfig.exports.import,
42 | format: 'es',
43 | sourcemap: true,
44 | },
45 | {
46 | file: pkg.publishConfig.exports.require,
47 | format: 'cjs',
48 | sourcemap: true,
49 | },
50 | ],
51 | };
52 |
--------------------------------------------------------------------------------
/sandboxes/bar/grouped/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | CategoryScale,
5 | LinearScale,
6 | BarElement,
7 | Title,
8 | Tooltip,
9 | Legend,
10 | } from 'chart.js';
11 | import { Bar } from 'react-chartjs-2';
12 | import faker from 'faker';
13 |
14 | ChartJS.register(
15 | CategoryScale,
16 | LinearScale,
17 | BarElement,
18 | Title,
19 | Tooltip,
20 | Legend
21 | );
22 |
23 | export const options = {
24 | plugins: {
25 | title: {
26 | display: true,
27 | text: 'Chart.js Bar Chart - Stacked',
28 | },
29 | },
30 | responsive: true,
31 | interaction: {
32 | mode: 'index' as const,
33 | intersect: false,
34 | },
35 | scales: {
36 | x: {
37 | stacked: true,
38 | },
39 | y: {
40 | stacked: true,
41 | },
42 | },
43 | };
44 |
45 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
46 |
47 | export const data = {
48 | labels,
49 | datasets: [
50 | {
51 | label: 'Dataset 1',
52 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
53 | backgroundColor: 'rgb(255, 99, 132)',
54 | stack: 'Stack 0',
55 | },
56 | {
57 | label: 'Dataset 2',
58 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
59 | backgroundColor: 'rgb(75, 192, 192)',
60 | stack: 'Stack 0',
61 | },
62 | {
63 | label: 'Dataset 3',
64 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
65 | backgroundColor: 'rgb(53, 162, 235)',
66 | stack: 'Stack 1',
67 | },
68 | ],
69 | };
70 |
71 | export function App() {
72 | return ;
73 | }
74 |
--------------------------------------------------------------------------------
/sandboxes/bar/grouped/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/bar/grouped/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/bar/grouped/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/bar/grouped/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/bar/horizontal/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | CategoryScale,
5 | LinearScale,
6 | BarElement,
7 | Title,
8 | Tooltip,
9 | Legend,
10 | } from 'chart.js';
11 | import { Bar } from 'react-chartjs-2';
12 | import faker from 'faker';
13 |
14 | ChartJS.register(
15 | CategoryScale,
16 | LinearScale,
17 | BarElement,
18 | Title,
19 | Tooltip,
20 | Legend
21 | );
22 |
23 | export const options = {
24 | indexAxis: 'y' as const,
25 | elements: {
26 | bar: {
27 | borderWidth: 2,
28 | },
29 | },
30 | responsive: true,
31 | plugins: {
32 | legend: {
33 | position: 'right' as const,
34 | },
35 | title: {
36 | display: true,
37 | text: 'Chart.js Horizontal Bar Chart',
38 | },
39 | },
40 | };
41 |
42 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
43 |
44 | export const data = {
45 | labels,
46 | datasets: [
47 | {
48 | label: 'Dataset 1',
49 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
50 | borderColor: 'rgb(255, 99, 132)',
51 | backgroundColor: 'rgba(255, 99, 132, 0.5)',
52 | },
53 | {
54 | label: 'Dataset 2',
55 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
56 | borderColor: 'rgb(53, 162, 235)',
57 | backgroundColor: 'rgba(53, 162, 235, 0.5)',
58 | },
59 | ],
60 | };
61 |
62 | export function App() {
63 | return ;
64 | }
65 |
--------------------------------------------------------------------------------
/sandboxes/bar/horizontal/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/bar/horizontal/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/bar/horizontal/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/bar/horizontal/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/bar/stacked/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | CategoryScale,
5 | LinearScale,
6 | BarElement,
7 | Title,
8 | Tooltip,
9 | Legend,
10 | } from 'chart.js';
11 | import { Bar } from 'react-chartjs-2';
12 | import faker from 'faker';
13 |
14 | ChartJS.register(
15 | CategoryScale,
16 | LinearScale,
17 | BarElement,
18 | Title,
19 | Tooltip,
20 | Legend
21 | );
22 |
23 | export const options = {
24 | plugins: {
25 | title: {
26 | display: true,
27 | text: 'Chart.js Bar Chart - Stacked',
28 | },
29 | },
30 | responsive: true,
31 | scales: {
32 | x: {
33 | stacked: true,
34 | },
35 | y: {
36 | stacked: true,
37 | },
38 | },
39 | };
40 |
41 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
42 |
43 | export const data = {
44 | labels,
45 | datasets: [
46 | {
47 | label: 'Dataset 1',
48 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
49 | backgroundColor: 'rgb(255, 99, 132)',
50 | },
51 | {
52 | label: 'Dataset 2',
53 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
54 | backgroundColor: 'rgb(75, 192, 192)',
55 | },
56 | {
57 | label: 'Dataset 3',
58 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
59 | backgroundColor: 'rgb(53, 162, 235)',
60 | },
61 | ],
62 | };
63 |
64 | export function App() {
65 | return ;
66 | }
67 |
--------------------------------------------------------------------------------
/sandboxes/bar/stacked/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/bar/stacked/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/bar/stacked/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/bar/stacked/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/bar/vertical/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | CategoryScale,
5 | LinearScale,
6 | BarElement,
7 | Title,
8 | Tooltip,
9 | Legend,
10 | } from 'chart.js';
11 | import { Bar } from 'react-chartjs-2';
12 | import faker from 'faker';
13 |
14 | ChartJS.register(
15 | CategoryScale,
16 | LinearScale,
17 | BarElement,
18 | Title,
19 | Tooltip,
20 | Legend
21 | );
22 |
23 | export const options = {
24 | responsive: true,
25 | plugins: {
26 | legend: {
27 | position: 'top' as const,
28 | },
29 | title: {
30 | display: true,
31 | text: 'Chart.js Bar Chart',
32 | },
33 | },
34 | };
35 |
36 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
37 |
38 | export const data = {
39 | labels,
40 | datasets: [
41 | {
42 | label: 'Dataset 1',
43 | data: labels.map(() => faker.datatype.number({ min: 0, max: 1000 })),
44 | backgroundColor: 'rgba(255, 99, 132, 0.5)',
45 | },
46 | {
47 | label: 'Dataset 2',
48 | data: labels.map(() => faker.datatype.number({ min: 0, max: 1000 })),
49 | backgroundColor: 'rgba(53, 162, 235, 0.5)',
50 | },
51 | ],
52 | };
53 |
54 | export function App() {
55 | return ;
56 | }
57 |
--------------------------------------------------------------------------------
/sandboxes/bar/vertical/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/bar/vertical/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/bar/vertical/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/bar/vertical/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/bubble/default/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | LinearScale,
5 | PointElement,
6 | Tooltip,
7 | Legend,
8 | } from 'chart.js';
9 | import { Bubble } from 'react-chartjs-2';
10 | import faker from 'faker';
11 |
12 | ChartJS.register(LinearScale, PointElement, Tooltip, Legend);
13 |
14 | export const options = {
15 | scales: {
16 | y: {
17 | beginAtZero: true,
18 | },
19 | },
20 | };
21 |
22 | export const data = {
23 | datasets: [
24 | {
25 | label: 'Red dataset',
26 | data: Array.from({ length: 50 }, () => ({
27 | x: faker.datatype.number({ min: -100, max: 100 }),
28 | y: faker.datatype.number({ min: -100, max: 100 }),
29 | r: faker.datatype.number({ min: 5, max: 20 }),
30 | })),
31 | backgroundColor: 'rgba(255, 99, 132, 0.5)',
32 | },
33 | {
34 | label: 'Blue dataset',
35 | data: Array.from({ length: 50 }, () => ({
36 | x: faker.datatype.number({ min: -100, max: 100 }),
37 | y: faker.datatype.number({ min: -100, max: 100 }),
38 | r: faker.datatype.number({ min: 5, max: 20 }),
39 | })),
40 | backgroundColor: 'rgba(53, 162, 235, 0.5)',
41 | },
42 | ],
43 | };
44 |
45 | export function App() {
46 | return ;
47 | }
48 |
--------------------------------------------------------------------------------
/sandboxes/bubble/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/bubble/default/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/bubble/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/bubble/default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/chart/canvas/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect, useState } from 'react';
2 | import type { ChartData, ChartArea } from 'chart.js';
3 | import {
4 | Chart as ChartJS,
5 | CategoryScale,
6 | LinearScale,
7 | PointElement,
8 | LineElement,
9 | Tooltip,
10 | Legend,
11 | } from 'chart.js';
12 | import { Chart } from 'react-chartjs-2';
13 | import faker from 'faker';
14 |
15 | ChartJS.register(
16 | CategoryScale,
17 | LinearScale,
18 | PointElement,
19 | LineElement,
20 | Tooltip,
21 | Legend
22 | );
23 |
24 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
25 | const colors = [
26 | 'red',
27 | 'orange',
28 | 'yellow',
29 | 'lime',
30 | 'green',
31 | 'teal',
32 | 'blue',
33 | 'purple',
34 | ];
35 |
36 | export const data = {
37 | labels,
38 | datasets: [
39 | {
40 | label: 'Dataset 1',
41 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
42 | },
43 | {
44 | label: 'Dataset 2',
45 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
46 | },
47 | ],
48 | };
49 |
50 | function createGradient(ctx: CanvasRenderingContext2D, area: ChartArea) {
51 | const colorStart = faker.random.arrayElement(colors);
52 | const colorMid = faker.random.arrayElement(
53 | colors.filter(color => color !== colorStart)
54 | );
55 | const colorEnd = faker.random.arrayElement(
56 | colors.filter(color => color !== colorStart && color !== colorMid)
57 | );
58 |
59 | const gradient = ctx.createLinearGradient(0, area.bottom, 0, area.top);
60 |
61 | gradient.addColorStop(0, colorStart);
62 | gradient.addColorStop(0.5, colorMid);
63 | gradient.addColorStop(1, colorEnd);
64 |
65 | return gradient;
66 | }
67 |
68 | export function App() {
69 | const chartRef = useRef(null);
70 | const [chartData, setChartData] = useState>({
71 | datasets: [],
72 | });
73 |
74 | useEffect(() => {
75 | const chart = chartRef.current;
76 |
77 | if (!chart) {
78 | return;
79 | }
80 |
81 | const chartData = {
82 | ...data,
83 | datasets: data.datasets.map(dataset => ({
84 | ...dataset,
85 | borderColor: createGradient(chart.ctx, chart.chartArea),
86 | })),
87 | };
88 |
89 | setChartData(chartData);
90 | }, []);
91 |
92 | return ;
93 | }
94 |
--------------------------------------------------------------------------------
/sandboxes/chart/canvas/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/chart/canvas/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/chart/canvas/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/chart/canvas/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/chart/events/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { MouseEvent, useRef } from 'react';
2 | import type { InteractionItem } from 'chart.js';
3 | import {
4 | Chart as ChartJS,
5 | LinearScale,
6 | CategoryScale,
7 | BarElement,
8 | PointElement,
9 | LineElement,
10 | Legend,
11 | Tooltip,
12 | } from 'chart.js';
13 | import {
14 | Chart,
15 | getDatasetAtEvent,
16 | getElementAtEvent,
17 | getElementsAtEvent,
18 | } from 'react-chartjs-2';
19 | import faker from 'faker';
20 |
21 | ChartJS.register(
22 | LinearScale,
23 | CategoryScale,
24 | BarElement,
25 | PointElement,
26 | LineElement,
27 | Legend,
28 | Tooltip
29 | );
30 |
31 | export const options = {
32 | scales: {
33 | y: {
34 | beginAtZero: true,
35 | },
36 | },
37 | };
38 |
39 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
40 |
41 | export const data = {
42 | labels,
43 | datasets: [
44 | {
45 | type: 'line' as const,
46 | label: 'Dataset 1',
47 | borderColor: 'rgb(255, 99, 132)',
48 | borderWidth: 2,
49 | fill: false,
50 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
51 | },
52 | {
53 | type: 'bar' as const,
54 | label: 'Dataset 2',
55 | backgroundColor: 'rgb(75, 192, 192)',
56 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
57 | borderColor: 'white',
58 | borderWidth: 2,
59 | },
60 | {
61 | type: 'bar' as const,
62 | label: 'Dataset 3',
63 | backgroundColor: 'rgb(53, 162, 235)',
64 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
65 | },
66 | ],
67 | };
68 |
69 | export function App() {
70 | const printDatasetAtEvent = (dataset: InteractionItem[]) => {
71 | if (!dataset.length) return;
72 |
73 | const datasetIndex = dataset[0].datasetIndex;
74 |
75 | console.log(data.datasets[datasetIndex].label);
76 | };
77 |
78 | const printElementAtEvent = (element: InteractionItem[]) => {
79 | if (!element.length) return;
80 |
81 | const { datasetIndex, index } = element[0];
82 |
83 | console.log(data.labels[index], data.datasets[datasetIndex].data[index]);
84 | };
85 |
86 | const printElementsAtEvent = (elements: InteractionItem[]) => {
87 | if (!elements.length) return;
88 |
89 | console.log(elements.length);
90 | };
91 |
92 | const chartRef = useRef(null);
93 |
94 | const onClick = (event: MouseEvent) => {
95 | const { current: chart } = chartRef;
96 |
97 | if (!chart) {
98 | return;
99 | }
100 |
101 | printDatasetAtEvent(getDatasetAtEvent(chart, event));
102 | printElementAtEvent(getElementAtEvent(chart, event));
103 | printElementsAtEvent(getElementsAtEvent(chart, event));
104 | };
105 |
106 | return (
107 |
114 | );
115 | }
116 |
--------------------------------------------------------------------------------
/sandboxes/chart/events/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/chart/events/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/chart/events/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/chart/events/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/chart/multitype/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | LinearScale,
5 | CategoryScale,
6 | BarElement,
7 | PointElement,
8 | LineElement,
9 | Legend,
10 | Tooltip,
11 | LineController,
12 | BarController,
13 | } from 'chart.js';
14 | import { Chart } from 'react-chartjs-2';
15 | import faker from 'faker';
16 |
17 | ChartJS.register(
18 | LinearScale,
19 | CategoryScale,
20 | BarElement,
21 | PointElement,
22 | LineElement,
23 | Legend,
24 | Tooltip,
25 | LineController,
26 | BarController
27 | );
28 |
29 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
30 |
31 | export const data = {
32 | labels,
33 | datasets: [
34 | {
35 | type: 'line' as const,
36 | label: 'Dataset 1',
37 | borderColor: 'rgb(255, 99, 132)',
38 | borderWidth: 2,
39 | fill: false,
40 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
41 | },
42 | {
43 | type: 'bar' as const,
44 | label: 'Dataset 2',
45 | backgroundColor: 'rgb(75, 192, 192)',
46 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
47 | borderColor: 'white',
48 | borderWidth: 2,
49 | },
50 | {
51 | type: 'bar' as const,
52 | label: 'Dataset 3',
53 | backgroundColor: 'rgb(53, 162, 235)',
54 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
55 | },
56 | ],
57 | };
58 |
59 | export function App() {
60 | return ;
61 | }
62 |
--------------------------------------------------------------------------------
/sandboxes/chart/multitype/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/chart/multitype/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/chart/multitype/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/chart/multitype/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/chart/ref/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect } from 'react';
2 | import {
3 | Chart as ChartJS,
4 | LinearScale,
5 | CategoryScale,
6 | BarElement,
7 | PointElement,
8 | LineElement,
9 | Legend,
10 | Tooltip,
11 | } from 'chart.js';
12 | import { Chart } from 'react-chartjs-2';
13 | import faker from 'faker';
14 |
15 | ChartJS.register(
16 | LinearScale,
17 | CategoryScale,
18 | BarElement,
19 | PointElement,
20 | LineElement,
21 | Legend,
22 | Tooltip
23 | );
24 |
25 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
26 |
27 | export const data = {
28 | labels,
29 | datasets: [
30 | {
31 | type: 'line' as const,
32 | label: 'Dataset 1',
33 | borderColor: 'rgb(255, 99, 132)',
34 | borderWidth: 2,
35 | fill: false,
36 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
37 | },
38 | {
39 | type: 'bar' as const,
40 | label: 'Dataset 2',
41 | backgroundColor: 'rgb(75, 192, 192)',
42 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
43 | borderColor: 'white',
44 | borderWidth: 2,
45 | },
46 | {
47 | type: 'bar' as const,
48 | label: 'Dataset 3',
49 | backgroundColor: 'rgb(53, 162, 235)',
50 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
51 | },
52 | ],
53 | };
54 |
55 | function triggerTooltip(chart: ChartJS | null) {
56 | const tooltip = chart?.tooltip;
57 |
58 | if (!tooltip) {
59 | return;
60 | }
61 |
62 | if (tooltip.getActiveElements().length > 0) {
63 | tooltip.setActiveElements([], { x: 0, y: 0 });
64 | } else {
65 | const { chartArea } = chart;
66 |
67 | tooltip.setActiveElements(
68 | [
69 | {
70 | datasetIndex: 0,
71 | index: 2,
72 | },
73 | {
74 | datasetIndex: 1,
75 | index: 2,
76 | },
77 | ],
78 | {
79 | x: (chartArea.left + chartArea.right) / 2,
80 | y: (chartArea.top + chartArea.bottom) / 2,
81 | }
82 | );
83 | }
84 |
85 | chart.update();
86 | }
87 |
88 | export function App() {
89 | const chartRef = useRef(null);
90 |
91 | useEffect(() => {
92 | const chart = chartRef.current;
93 |
94 | triggerTooltip(chart);
95 | }, []);
96 |
97 | return ;
98 | }
99 |
--------------------------------------------------------------------------------
/sandboxes/chart/ref/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/chart/ref/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/chart/ref/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/chart/ref/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/default/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
3 | import { Doughnut } from 'react-chartjs-2';
4 |
5 | ChartJS.register(ArcElement, Tooltip, Legend);
6 |
7 | export const data = {
8 | labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
9 | datasets: [
10 | {
11 | label: '# of Votes',
12 | data: [12, 19, 3, 5, 2, 3],
13 | backgroundColor: [
14 | 'rgba(255, 99, 132, 0.2)',
15 | 'rgba(54, 162, 235, 0.2)',
16 | 'rgba(255, 206, 86, 0.2)',
17 | 'rgba(75, 192, 192, 0.2)',
18 | 'rgba(153, 102, 255, 0.2)',
19 | 'rgba(255, 159, 64, 0.2)',
20 | ],
21 | borderColor: [
22 | 'rgba(255, 99, 132, 1)',
23 | 'rgba(54, 162, 235, 1)',
24 | 'rgba(255, 206, 86, 1)',
25 | 'rgba(75, 192, 192, 1)',
26 | 'rgba(153, 102, 255, 1)',
27 | 'rgba(255, 159, 64, 1)',
28 | ],
29 | borderWidth: 1,
30 | },
31 | ],
32 | };
33 |
34 | export function App() {
35 | return ;
36 | }
37 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/default/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/doughnut/default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/line/area/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | CategoryScale,
5 | LinearScale,
6 | PointElement,
7 | LineElement,
8 | Title,
9 | Tooltip,
10 | Filler,
11 | Legend,
12 | } from 'chart.js';
13 | import { Line } from 'react-chartjs-2';
14 | import faker from 'faker';
15 |
16 | ChartJS.register(
17 | CategoryScale,
18 | LinearScale,
19 | PointElement,
20 | LineElement,
21 | Title,
22 | Tooltip,
23 | Filler,
24 | Legend
25 | );
26 |
27 | export const options = {
28 | responsive: true,
29 | plugins: {
30 | legend: {
31 | position: 'top' as const,
32 | },
33 | title: {
34 | display: true,
35 | text: 'Chart.js Line Chart',
36 | },
37 | },
38 | };
39 |
40 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
41 |
42 | export const data = {
43 | labels,
44 | datasets: [
45 | {
46 | fill: true,
47 | label: 'Dataset 2',
48 | data: labels.map(() => faker.datatype.number({ min: 0, max: 1000 })),
49 | borderColor: 'rgb(53, 162, 235)',
50 | backgroundColor: 'rgba(53, 162, 235, 0.5)',
51 | },
52 | ],
53 | };
54 |
55 | export function App() {
56 | return ;
57 | }
58 |
--------------------------------------------------------------------------------
/sandboxes/line/area/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/line/area/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/line/area/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/line/area/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/line/default/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | CategoryScale,
5 | LinearScale,
6 | PointElement,
7 | LineElement,
8 | Title,
9 | Tooltip,
10 | Legend,
11 | } from 'chart.js';
12 | import { Line } from 'react-chartjs-2';
13 | import faker from 'faker';
14 |
15 | ChartJS.register(
16 | CategoryScale,
17 | LinearScale,
18 | PointElement,
19 | LineElement,
20 | Title,
21 | Tooltip,
22 | Legend
23 | );
24 |
25 | export const options = {
26 | responsive: true,
27 | plugins: {
28 | legend: {
29 | position: 'top' as const,
30 | },
31 | title: {
32 | display: true,
33 | text: 'Chart.js Line Chart',
34 | },
35 | },
36 | };
37 |
38 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
39 |
40 | export const data = {
41 | labels,
42 | datasets: [
43 | {
44 | label: 'Dataset 1',
45 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
46 | borderColor: 'rgb(255, 99, 132)',
47 | backgroundColor: 'rgba(255, 99, 132, 0.5)',
48 | },
49 | {
50 | label: 'Dataset 2',
51 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
52 | borderColor: 'rgb(53, 162, 235)',
53 | backgroundColor: 'rgba(53, 162, 235, 0.5)',
54 | },
55 | ],
56 | };
57 |
58 | export function App() {
59 | return ;
60 | }
61 |
--------------------------------------------------------------------------------
/sandboxes/line/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/line/default/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/line/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/line/default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/line/multiaxis/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | CategoryScale,
5 | LinearScale,
6 | PointElement,
7 | LineElement,
8 | Title,
9 | Tooltip,
10 | Legend,
11 | } from 'chart.js';
12 | import { Line } from 'react-chartjs-2';
13 | import faker from 'faker';
14 |
15 | ChartJS.register(
16 | CategoryScale,
17 | LinearScale,
18 | PointElement,
19 | LineElement,
20 | Title,
21 | Tooltip,
22 | Legend
23 | );
24 |
25 | export const options = {
26 | responsive: true,
27 | interaction: {
28 | mode: 'index' as const,
29 | intersect: false,
30 | },
31 | stacked: false,
32 | plugins: {
33 | title: {
34 | display: true,
35 | text: 'Chart.js Line Chart - Multi Axis',
36 | },
37 | },
38 | scales: {
39 | y: {
40 | type: 'linear' as const,
41 | display: true,
42 | position: 'left' as const,
43 | },
44 | y1: {
45 | type: 'linear' as const,
46 | display: true,
47 | position: 'right' as const,
48 | grid: {
49 | drawOnChartArea: false,
50 | },
51 | },
52 | },
53 | };
54 |
55 | const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
56 |
57 | export const data = {
58 | labels,
59 | datasets: [
60 | {
61 | label: 'Dataset 1',
62 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
63 | borderColor: 'rgb(255, 99, 132)',
64 | backgroundColor: 'rgba(255, 99, 132, 0.5)',
65 | yAxisID: 'y',
66 | },
67 | {
68 | label: 'Dataset 2',
69 | data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
70 | borderColor: 'rgb(53, 162, 235)',
71 | backgroundColor: 'rgba(53, 162, 235, 0.5)',
72 | yAxisID: 'y1',
73 | },
74 | ],
75 | };
76 |
77 | export function App() {
78 | return ;
79 | }
80 |
--------------------------------------------------------------------------------
/sandboxes/line/multiaxis/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/line/multiaxis/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/line/multiaxis/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/line/multiaxis/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/pie/default/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';
3 | import { Pie } from 'react-chartjs-2';
4 |
5 | ChartJS.register(ArcElement, Tooltip, Legend);
6 |
7 | export const data = {
8 | labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
9 | datasets: [
10 | {
11 | label: '# of Votes',
12 | data: [12, 19, 3, 5, 2, 3],
13 | backgroundColor: [
14 | 'rgba(255, 99, 132, 0.2)',
15 | 'rgba(54, 162, 235, 0.2)',
16 | 'rgba(255, 206, 86, 0.2)',
17 | 'rgba(75, 192, 192, 0.2)',
18 | 'rgba(153, 102, 255, 0.2)',
19 | 'rgba(255, 159, 64, 0.2)',
20 | ],
21 | borderColor: [
22 | 'rgba(255, 99, 132, 1)',
23 | 'rgba(54, 162, 235, 1)',
24 | 'rgba(255, 206, 86, 1)',
25 | 'rgba(75, 192, 192, 1)',
26 | 'rgba(153, 102, 255, 1)',
27 | 'rgba(255, 159, 64, 1)',
28 | ],
29 | borderWidth: 1,
30 | },
31 | ],
32 | };
33 |
34 | export function App() {
35 | return ;
36 | }
37 |
--------------------------------------------------------------------------------
/sandboxes/pie/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/pie/default/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/pie/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/pie/default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/polarArea/default/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | RadialLinearScale,
5 | ArcElement,
6 | Tooltip,
7 | Legend,
8 | } from 'chart.js';
9 | import { PolarArea } from 'react-chartjs-2';
10 |
11 | ChartJS.register(RadialLinearScale, ArcElement, Tooltip, Legend);
12 |
13 | export const data = {
14 | labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
15 | datasets: [
16 | {
17 | label: '# of Votes',
18 | data: [12, 19, 3, 5, 2, 3],
19 | backgroundColor: [
20 | 'rgba(255, 99, 132, 0.5)',
21 | 'rgba(54, 162, 235, 0.5)',
22 | 'rgba(255, 206, 86, 0.5)',
23 | 'rgba(75, 192, 192, 0.5)',
24 | 'rgba(153, 102, 255, 0.5)',
25 | 'rgba(255, 159, 64, 0.5)',
26 | ],
27 | borderWidth: 1,
28 | },
29 | ],
30 | };
31 |
32 | export function App() {
33 | return ;
34 | }
35 |
--------------------------------------------------------------------------------
/sandboxes/polarArea/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/polarArea/default/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/polarArea/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/polarArea/default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/radar/default/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | RadialLinearScale,
5 | PointElement,
6 | LineElement,
7 | Filler,
8 | Tooltip,
9 | Legend,
10 | } from 'chart.js';
11 | import { Radar } from 'react-chartjs-2';
12 |
13 | ChartJS.register(
14 | RadialLinearScale,
15 | PointElement,
16 | LineElement,
17 | Filler,
18 | Tooltip,
19 | Legend
20 | );
21 |
22 | export const data = {
23 | labels: ['Thing 1', 'Thing 2', 'Thing 3', 'Thing 4', 'Thing 5', 'Thing 6'],
24 | datasets: [
25 | {
26 | label: '# of Votes',
27 | data: [2, 9, 3, 5, 2, 3],
28 | backgroundColor: 'rgba(255, 99, 132, 0.2)',
29 | borderColor: 'rgba(255, 99, 132, 1)',
30 | borderWidth: 1,
31 | },
32 | ],
33 | };
34 |
35 | export function App() {
36 | return ;
37 | }
38 |
--------------------------------------------------------------------------------
/sandboxes/radar/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/radar/default/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/radar/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/radar/default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/scatter/default/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Chart as ChartJS,
4 | LinearScale,
5 | PointElement,
6 | LineElement,
7 | Tooltip,
8 | Legend,
9 | } from 'chart.js';
10 | import { Scatter } from 'react-chartjs-2';
11 | import faker from 'faker';
12 |
13 | ChartJS.register(LinearScale, PointElement, LineElement, Tooltip, Legend);
14 |
15 | export const options = {
16 | scales: {
17 | y: {
18 | beginAtZero: true,
19 | },
20 | },
21 | };
22 |
23 | export const data = {
24 | datasets: [
25 | {
26 | label: 'A dataset',
27 | data: Array.from({ length: 100 }, () => ({
28 | x: faker.datatype.number({ min: -100, max: 100 }),
29 | y: faker.datatype.number({ min: -100, max: 100 }),
30 | })),
31 | backgroundColor: 'rgba(255, 99, 132, 1)',
32 | },
33 | ],
34 | };
35 |
36 | export function App() {
37 | return ;
38 | }
39 |
--------------------------------------------------------------------------------
/sandboxes/scatter/default/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sandboxes/scatter/default/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import { App } from './App.js';
5 |
6 | const rootElement = document.getElementById('root');
7 | createRoot(rootElement!).render();
8 |
--------------------------------------------------------------------------------
/sandboxes/scatter/default/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "module",
3 | "scripts": {
4 | "start": "vite"
5 | },
6 | "dependencies": {
7 | "chart.js": "^4.0.0",
8 | "faker": "5.5.3",
9 | "react": "18.2.0",
10 | "react-chartjs-2": "^5.0.0",
11 | "react-dom": "18.2.0"
12 | },
13 | "devDependencies": {
14 | "@types/faker": "5.5.9",
15 | "@types/react": "18.0.26",
16 | "@types/react-dom": "18.0.10",
17 | "@vitejs/plugin-react": "^3.0.0",
18 | "typescript": "4.9.4",
19 | "vite": "^4.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sandboxes/scatter/default/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | });
7 |
--------------------------------------------------------------------------------
/sandboxes/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "paths": {
6 | "react-chartjs-2": ["../src"]
7 | }
8 | },
9 | "include": ["."]
10 | }
11 |
--------------------------------------------------------------------------------
/src/chart.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useRef, forwardRef } from 'react';
2 | import { Chart as ChartJS } from 'chart.js';
3 | import type { ChartType, DefaultDataPoint } from 'chart.js';
4 |
5 | import type { ForwardedRef, ChartProps, BaseChartComponent } from './types.js';
6 | import {
7 | reforwardRef,
8 | cloneData,
9 | setOptions,
10 | setLabels,
11 | setDatasets,
12 | } from './utils.js';
13 |
14 | function ChartComponent<
15 | TType extends ChartType = ChartType,
16 | TData = DefaultDataPoint,
17 | TLabel = unknown
18 | >(
19 | props: ChartProps,
20 | ref: ForwardedRef>
21 | ) {
22 | const {
23 | height = 150,
24 | width = 300,
25 | redraw = false,
26 | datasetIdKey,
27 | type,
28 | data,
29 | options,
30 | plugins = [],
31 | fallbackContent,
32 | updateMode,
33 | ...canvasProps
34 | } = props as ChartProps;
35 | const canvasRef = useRef(null);
36 | const chartRef = useRef();
37 |
38 | const renderChart = () => {
39 | if (!canvasRef.current) return;
40 |
41 | chartRef.current = new ChartJS(canvasRef.current, {
42 | type,
43 | data: cloneData(data, datasetIdKey),
44 | options: options && { ...options },
45 | plugins,
46 | });
47 |
48 | reforwardRef(ref, chartRef.current);
49 | };
50 |
51 | const destroyChart = () => {
52 | reforwardRef(ref, null);
53 |
54 | if (chartRef.current) {
55 | chartRef.current.destroy();
56 | chartRef.current = null;
57 | }
58 | };
59 |
60 | useEffect(() => {
61 | if (!redraw && chartRef.current && options) {
62 | setOptions(chartRef.current, options);
63 | }
64 | }, [redraw, options]);
65 |
66 | useEffect(() => {
67 | if (!redraw && chartRef.current) {
68 | setLabels(chartRef.current.config.data, data.labels);
69 | }
70 | }, [redraw, data.labels]);
71 |
72 | useEffect(() => {
73 | if (!redraw && chartRef.current && data.datasets) {
74 | setDatasets(chartRef.current.config.data, data.datasets, datasetIdKey);
75 | }
76 | }, [redraw, data.datasets]);
77 |
78 | useEffect(() => {
79 | if (!chartRef.current) return;
80 |
81 | if (redraw) {
82 | destroyChart();
83 | setTimeout(renderChart);
84 | } else {
85 | chartRef.current.update(updateMode);
86 | }
87 | }, [redraw, options, data.labels, data.datasets, updateMode]);
88 |
89 | useEffect(() => {
90 | if (!chartRef.current) return;
91 |
92 | destroyChart();
93 | setTimeout(renderChart);
94 | }, [type]);
95 |
96 | useEffect(() => {
97 | renderChart();
98 |
99 | return () => destroyChart();
100 | }, []);
101 |
102 | return (
103 |
112 | );
113 | }
114 |
115 | export const Chart = forwardRef(ChartComponent) as BaseChartComponent;
116 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export type { ChartProps } from './types.js';
2 | export * from './chart.js';
3 | export * from './typedCharts.js';
4 | export {
5 | getDatasetAtEvent,
6 | getElementAtEvent,
7 | getElementsAtEvent,
8 | } from './utils.js';
9 |
--------------------------------------------------------------------------------
/src/typedCharts.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef } from 'react';
2 | import {
3 | Chart as ChartJS,
4 | LineController,
5 | BarController,
6 | RadarController,
7 | DoughnutController,
8 | PolarAreaController,
9 | BubbleController,
10 | PieController,
11 | ScatterController,
12 | } from 'chart.js';
13 | import type { ChartType, ChartComponentLike } from 'chart.js';
14 |
15 | import type {
16 | ChartProps,
17 | ChartJSOrUndefined,
18 | TypedChartComponent,
19 | } from './types.js';
20 | import { Chart } from './chart.js';
21 |
22 | function createTypedChart(
23 | type: T,
24 | registerables: ChartComponentLike
25 | ) {
26 | ChartJS.register(registerables);
27 |
28 | return forwardRef, Omit, 'type'>>(
29 | (props, ref) =>
30 | ) as TypedChartComponent;
31 | }
32 |
33 | export const Line = /* #__PURE__ */ createTypedChart('line', LineController);
34 |
35 | export const Bar = /* #__PURE__ */ createTypedChart('bar', BarController);
36 |
37 | export const Radar = /* #__PURE__ */ createTypedChart('radar', RadarController);
38 |
39 | export const Doughnut = /* #__PURE__ */ createTypedChart(
40 | 'doughnut',
41 | DoughnutController
42 | );
43 |
44 | export const PolarArea = /* #__PURE__ */ createTypedChart(
45 | 'polarArea',
46 | PolarAreaController
47 | );
48 |
49 | export const Bubble = /* #__PURE__ */ createTypedChart(
50 | 'bubble',
51 | BubbleController
52 | );
53 |
54 | export const Pie = /* #__PURE__ */ createTypedChart('pie', PieController);
55 |
56 | export const Scatter = /* #__PURE__ */ createTypedChart(
57 | 'scatter',
58 | ScatterController
59 | );
60 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { CanvasHTMLAttributes, MutableRefObject, ReactNode } from 'react';
2 | import type {
3 | Chart,
4 | ChartType,
5 | ChartData,
6 | ChartOptions,
7 | DefaultDataPoint,
8 | Plugin,
9 | UpdateMode,
10 | } from 'chart.js';
11 |
12 | export type ForwardedRef =
13 | | ((instance: T | null) => void)
14 | | MutableRefObject
15 | | null;
16 |
17 | export interface ChartProps<
18 | TType extends ChartType = ChartType,
19 | TData = DefaultDataPoint,
20 | TLabel = unknown
21 | > extends CanvasHTMLAttributes {
22 | /**
23 | * Chart.js chart type
24 | */
25 | type: TType;
26 | /**
27 | * The data object that is passed into the Chart.js chart
28 | * @see https://www.chartjs.org/docs/latest/getting-started/
29 | */
30 | data: ChartData;
31 | /**
32 | * The options object that is passed into the Chart.js chart
33 | * @see https://www.chartjs.org/docs/latest/general/options.html
34 | * @default {}
35 | */
36 | options?: ChartOptions;
37 | /**
38 | * The plugins array that is passed into the Chart.js chart
39 | * @see https://www.chartjs.org/docs/latest/developers/plugins.html
40 | * @default []
41 | */
42 | plugins?: Plugin[];
43 | /**
44 | * Teardown and redraw chart on every update
45 | * @default false
46 | */
47 | redraw?: boolean;
48 | /**
49 | * Key name to identificate dataset
50 | * @default 'label'
51 | */
52 | datasetIdKey?: string;
53 | /**
54 | * A fallback for when the canvas cannot be rendered. Can be used for accessible chart descriptions
55 | * @see https://www.chartjs.org/docs/latest/general/accessibility.html
56 | * @default null
57 | * @todo Replace with `children` prop.
58 | */
59 | fallbackContent?: ReactNode;
60 | /**
61 | * A mode string to indicate transition configuration should be used.
62 | * @see https://www.chartjs.org/docs/latest/developers/api.html#update-mode
63 | */
64 | updateMode?: UpdateMode;
65 | }
66 |
67 | /**
68 | * @todo Replace `undefined` with `null`
69 | */
70 | export type ChartJSOrUndefined<
71 | TType extends ChartType = ChartType,
72 | TData = DefaultDataPoint,
73 | TLabel = unknown
74 | > = Chart | undefined;
75 |
76 | export type BaseChartComponent = <
77 | TType extends ChartType = ChartType,
78 | TData = DefaultDataPoint,
79 | TLabel = unknown
80 | >(
81 | props: ChartProps & {
82 | ref?: ForwardedRef>;
83 | }
84 | ) => JSX.Element;
85 |
86 | export type TypedChartComponent = <
87 | TData = DefaultDataPoint,
88 | TLabel = unknown
89 | >(
90 | props: Omit, 'type'> & {
91 | ref?: ForwardedRef>;
92 | }
93 | ) => JSX.Element;
94 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import type { MouseEvent } from 'react';
2 | import type {
3 | ChartType,
4 | ChartData,
5 | DefaultDataPoint,
6 | ChartDataset,
7 | ChartOptions,
8 | Chart,
9 | } from 'chart.js';
10 |
11 | import type { ForwardedRef } from './types.js';
12 |
13 | const defaultDatasetIdKey = 'label';
14 |
15 | export function reforwardRef(ref: ForwardedRef, value: T) {
16 | if (typeof ref === 'function') {
17 | ref(value);
18 | } else if (ref) {
19 | ref.current = value;
20 | }
21 | }
22 |
23 | export function setOptions<
24 | TType extends ChartType = ChartType,
25 | TData = DefaultDataPoint,
26 | TLabel = unknown
27 | >(chart: Chart, nextOptions: ChartOptions) {
28 | const options = chart.options;
29 |
30 | if (options && nextOptions) {
31 | Object.assign(options, nextOptions);
32 | }
33 | }
34 |
35 | export function setLabels<
36 | TType extends ChartType = ChartType,
37 | TData = DefaultDataPoint,
38 | TLabel = unknown
39 | >(
40 | currentData: ChartData,
41 | nextLabels: TLabel[] | undefined
42 | ) {
43 | currentData.labels = nextLabels;
44 | }
45 |
46 | export function setDatasets<
47 | TType extends ChartType = ChartType,
48 | TData = DefaultDataPoint,
49 | TLabel = unknown
50 | >(
51 | currentData: ChartData,
52 | nextDatasets: ChartDataset[],
53 | datasetIdKey = defaultDatasetIdKey
54 | ) {
55 | const addedDatasets: ChartDataset[] = [];
56 |
57 | currentData.datasets = nextDatasets.map(
58 | (nextDataset: Record) => {
59 | // given the new set, find it's current match
60 | const currentDataset = currentData.datasets.find(
61 | (dataset: Record) =>
62 | dataset[datasetIdKey] === nextDataset[datasetIdKey]
63 | );
64 |
65 | // There is no original to update, so simply add new one
66 | if (
67 | !currentDataset ||
68 | !nextDataset.data ||
69 | addedDatasets.includes(currentDataset)
70 | ) {
71 | return { ...nextDataset } as ChartDataset;
72 | }
73 |
74 | addedDatasets.push(currentDataset);
75 |
76 | Object.assign(currentDataset, nextDataset);
77 |
78 | return currentDataset;
79 | }
80 | );
81 | }
82 |
83 | export function cloneData<
84 | TType extends ChartType = ChartType,
85 | TData = DefaultDataPoint,
86 | TLabel = unknown
87 | >(data: ChartData, datasetIdKey = defaultDatasetIdKey) {
88 | const nextData: ChartData = {
89 | labels: [],
90 | datasets: [],
91 | };
92 |
93 | setLabels(nextData, data.labels);
94 | setDatasets(nextData, data.datasets, datasetIdKey);
95 |
96 | return nextData;
97 | }
98 |
99 | /**
100 | * Get dataset from mouse click event
101 | * @param chart - Chart.js instance
102 | * @param event - Mouse click event
103 | * @returns Dataset
104 | */
105 | export function getDatasetAtEvent(
106 | chart: Chart,
107 | event: MouseEvent
108 | ) {
109 | return chart.getElementsAtEventForMode(
110 | event.nativeEvent,
111 | 'dataset',
112 | { intersect: true },
113 | false
114 | );
115 | }
116 |
117 | /**
118 | * Get single dataset element from mouse click event
119 | * @param chart - Chart.js instance
120 | * @param event - Mouse click event
121 | * @returns Dataset
122 | */
123 | export function getElementAtEvent(
124 | chart: Chart,
125 | event: MouseEvent
126 | ) {
127 | return chart.getElementsAtEventForMode(
128 | event.nativeEvent,
129 | 'nearest',
130 | { intersect: true },
131 | false
132 | );
133 | }
134 |
135 | /**
136 | * Get all dataset elements from mouse click event
137 | * @param chart - Chart.js instance
138 | * @param event - Mouse click event
139 | * @returns Dataset
140 | */
141 | export function getElementsAtEvent(
142 | chart: Chart,
143 | event: MouseEvent
144 | ) {
145 | return chart.getElementsAtEventForMode(
146 | event.nativeEvent,
147 | 'index',
148 | { intersect: true },
149 | false
150 | );
151 | }
152 |
--------------------------------------------------------------------------------
/stories/Bar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import 'chart.js/auto';
3 | import { Bar } from '../src';
4 | import * as verticalBar from '../sandboxes/bar/vertical/App';
5 | import * as horizontalBar from '../sandboxes/bar/horizontal/App';
6 | import * as stackedBar from '../sandboxes/bar/stacked/App';
7 | import * as groupedBar from '../sandboxes/bar/grouped/App';
8 |
9 | export default {
10 | title: 'Components/Bar',
11 | component: Bar,
12 | parameters: {
13 | layout: 'centered',
14 | },
15 | args: {
16 | width: 500,
17 | height: 400,
18 | },
19 | };
20 |
21 | export const Vertical = args => ;
22 |
23 | Vertical.args = {
24 | data: verticalBar.data,
25 | options: verticalBar.options,
26 | };
27 |
28 | export const Horizontal = args => ;
29 |
30 | Horizontal.args = {
31 | data: horizontalBar.data,
32 | options: horizontalBar.options,
33 | };
34 |
35 | export const Stacked = args => ;
36 |
37 | Stacked.args = {
38 | data: stackedBar.data,
39 | options: stackedBar.options,
40 | };
41 |
42 | export const Grouped = args => ;
43 |
44 | Grouped.args = {
45 | data: groupedBar.data,
46 | options: groupedBar.options,
47 | };
48 |
--------------------------------------------------------------------------------
/stories/Bubble.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import 'chart.js/auto';
3 | import { Bubble } from '../src';
4 | import { data, options } from '../sandboxes/bubble/default/App';
5 |
6 | export default {
7 | title: 'Components/Bubble',
8 | component: Bubble,
9 | parameters: {
10 | layout: 'centered',
11 | },
12 | args: {
13 | width: 500,
14 | height: 400,
15 | },
16 | };
17 |
18 | export const Default = args => ;
19 |
20 | Default.args = {
21 | data,
22 | options,
23 | };
24 |
--------------------------------------------------------------------------------
/stories/Chart.data.ts:
--------------------------------------------------------------------------------
1 | import faker from 'faker';
2 | import { colorRed } from './data';
3 |
4 | export const dynamicOptions = {
5 | scales: {
6 | y: {
7 | beginAtZero: true,
8 | },
9 | },
10 | };
11 |
12 | export const getDynamicData = () => ({
13 | labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
14 | datasets: [
15 | {
16 | type: 'bar',
17 | label: 'Scale',
18 | data: Array.from({ length: 6 }, () =>
19 | faker.datatype.number({ min: -10, max: 10 })
20 | ),
21 | backgroundColor: [
22 | 'rgba(255, 99, 132, 0.2)',
23 | 'rgba(54, 162, 235, 0.2)',
24 | 'rgba(255, 206, 86, 0.2)',
25 | 'rgba(75, 192, 192, 0.2)',
26 | 'rgba(153, 102, 255, 0.2)',
27 | 'rgba(255, 159, 64, 0.2)',
28 | ],
29 | borderColor: [
30 | 'rgba(255, 99, 132, 1)',
31 | 'rgba(54, 162, 235, 1)',
32 | 'rgba(255, 206, 86, 1)',
33 | 'rgba(75, 192, 192, 1)',
34 | 'rgba(153, 102, 255, 1)',
35 | 'rgba(255, 159, 64, 1)',
36 | ],
37 | borderWidth: 1,
38 | },
39 | ],
40 | });
41 |
42 | export const sameData1 = {
43 | labels: [
44 | 'Jan',
45 | 'Feb',
46 | 'Mar',
47 | 'Apr',
48 | 'Mei',
49 | 'Jun',
50 | 'Jul',
51 | 'Aug',
52 | 'Sep',
53 | 'Oct',
54 | 'Nov',
55 | 'Dec',
56 | ],
57 | datasets: [
58 | {
59 | label: 'My First dataset',
60 | backgroundColor: 'rgba(75,192,192,0.4)',
61 | data: [33, 53, 85, 41, 44, 65, 61, 47, 52, 53, 62, 82],
62 | },
63 | {
64 | label: 'My Second dataset',
65 | backgroundColor: '#742774',
66 | data: [33, 25, 35, 51, 54, 76, 65, 40, 42, 39, 51, 55],
67 | },
68 | ],
69 | };
70 |
71 | export const sameData2 = {
72 | labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
73 | datasets: [
74 | {
75 | label: 'My First dataset',
76 | backgroundColor: 'rgba(75,192,192,0.4)',
77 | data: [42, 13, 45, 29, 44, 25, 27],
78 | },
79 | {
80 | label: 'My Second dataset',
81 | backgroundColor: '#742774',
82 | data: [33, 25, 35, 44, 50, 40, 48],
83 | },
84 | ],
85 | };
86 |
87 | export const decimationOptions = {
88 | // Turn off animations and data parsing for performance
89 | animation: false,
90 | parsing: false,
91 |
92 | interaction: {
93 | mode: 'nearest',
94 | axis: 'x',
95 | intersect: false,
96 | },
97 | plugins: {
98 | decimation: {
99 | enabled: true,
100 | algorithm: 'lttb',
101 | samples: 500,
102 | },
103 | },
104 | scales: {
105 | x: {
106 | type: 'time',
107 | ticks: {
108 | source: 'auto',
109 | // Disabled rotation for performance
110 | maxRotation: 0,
111 | autoSkip: true,
112 | },
113 | },
114 | },
115 | };
116 |
117 | export const getDecimationData = () => {
118 | const start = Date.now();
119 | const data = Array.from({ length: 100000 }, (_, i) => ({
120 | x: start + i * 30000,
121 | y: faker.datatype.number({ min: 0, max: Math.random() < 0.001 ? 100 : 20 }),
122 | }));
123 |
124 | return {
125 | datasets: [
126 | {
127 | borderColor: colorRed,
128 | borderWidth: 1,
129 | data,
130 | label: 'Large Dataset',
131 | radius: 0,
132 | },
133 | ],
134 | };
135 | };
136 |
--------------------------------------------------------------------------------
/stories/Chart.tsx:
--------------------------------------------------------------------------------
1 | import React, {
2 | MouseEvent,
3 | useRef,
4 | useState,
5 | useEffect,
6 | useReducer,
7 | useMemo,
8 | } from 'react';
9 | import 'chart.js/auto';
10 | import type { InteractionItem } from 'chart.js';
11 | import { Chart as ChartJS } from 'chart.js';
12 | import 'chartjs-adapter-date-fns';
13 | import annotationPlugin from 'chartjs-plugin-annotation';
14 | import zoomPlugin from 'chartjs-plugin-zoom';
15 | import {
16 | Chart,
17 | getDatasetAtEvent,
18 | getElementAtEvent,
19 | getElementsAtEvent,
20 | } from '../src';
21 | import * as multitypeChart from '../sandboxes/chart/multitype/App';
22 | import * as eventsChart from '../sandboxes/chart/events/App';
23 | import * as data from './Chart.data';
24 |
25 | ChartJS.register(annotationPlugin, zoomPlugin);
26 |
27 | export default {
28 | title: 'Components/Chart',
29 | component: Chart,
30 | parameters: {
31 | layout: 'centered',
32 | },
33 | args: {
34 | width: 500,
35 | height: 400,
36 | },
37 | };
38 |
39 | export const MultiType = args => ;
40 |
41 | MultiType.args = {
42 | data: multitypeChart.data,
43 | };
44 |
45 | export const Dynamic = args => {
46 | const [dynamicData, setDynamicData] = useState(data.getDynamicData);
47 |
48 | useEffect(() => {
49 | const interval = setInterval(
50 | () => setDynamicData(data.getDynamicData()),
51 | 3000
52 | );
53 |
54 | return () => clearInterval(interval);
55 | }, []);
56 |
57 | return ;
58 | };
59 |
60 | Dynamic.args = {
61 | options: data.dynamicOptions,
62 | };
63 |
64 | export const ClickEvents = ({
65 | onDatasetClick,
66 | onElementClick,
67 | onElementsClick,
68 | options,
69 | data,
70 | ...args
71 | }) => {
72 | const datasetAtEvent = (dataset: InteractionItem[]) => {
73 | if (!dataset.length) return;
74 |
75 | const datasetIndex = dataset[0].datasetIndex;
76 |
77 | onDatasetClick(data.datasets[datasetIndex].label);
78 | };
79 |
80 | const elementAtEvent = (element: InteractionItem[]) => {
81 | if (!element.length) return;
82 |
83 | const { datasetIndex, index } = element[0];
84 |
85 | onElementClick(data.labels[index], data.datasets[datasetIndex].data[index]);
86 | };
87 |
88 | const elementsAtEvent = (elements: InteractionItem[]) => {
89 | if (!elements.length) return;
90 |
91 | onElementsClick(elements);
92 | };
93 |
94 | const chartRef = useRef(null);
95 |
96 | const onClick = (event: MouseEvent) => {
97 | const { current: chart } = chartRef;
98 |
99 | if (!chart) {
100 | return;
101 | }
102 |
103 | datasetAtEvent(getDatasetAtEvent(chart, event));
104 | elementAtEvent(getElementAtEvent(chart, event));
105 | elementsAtEvent(getElementsAtEvent(chart, event));
106 | };
107 |
108 | return (
109 |
117 | );
118 | };
119 |
120 | ClickEvents.args = {
121 | options: eventsChart.options,
122 | data: eventsChart.data,
123 | };
124 |
125 | ClickEvents.argTypes = {
126 | onDatasetClick: { action: 'dataset clicked' },
127 | onElementClick: { action: 'element clicked' },
128 | onElementsClick: { action: 'elements clicked' },
129 | };
130 |
131 | export const Redraw = args => ;
132 |
133 | Redraw.args = {
134 | data: multitypeChart.data,
135 | redraw: true,
136 | };
137 |
138 | export const SameDataToggle = args => {
139 | const [currentData, toggleData] = useReducer(
140 | prevState =>
141 | prevState === data.sameData1 ? data.sameData2 : data.sameData1,
142 | data.sameData1
143 | );
144 |
145 | return ;
146 | };
147 |
148 | SameDataToggle.args = {
149 | type: 'bar',
150 | };
151 |
152 | export const Decimation = args => {
153 | const [currentData, toggleData] = useReducer(
154 | data.getDecimationData,
155 | data.getDecimationData()
156 | );
157 |
158 | return ;
159 | };
160 |
161 | Decimation.args = {
162 | type: 'line',
163 | options: data.decimationOptions,
164 | };
165 |
166 | export const DynamicOptions = args => {
167 | const [yMax, setYMax] = useState(100);
168 | const options = useMemo(
169 | () => ({
170 | plugins: {
171 | annotation: {
172 | annotations: {
173 | box1: {
174 | type: 'box',
175 | xMin: 1,
176 | xMax: 2,
177 | yMin: 50,
178 | yMax: yMax,
179 | backgroundColor: 'rgba(255, 99, 132, 0.25)',
180 | },
181 | },
182 | },
183 | zoom: {
184 | zoom: {
185 | wheel: {
186 | enabled: true,
187 | },
188 | pinch: {
189 | enabled: true,
190 | },
191 | mode: 'xy',
192 | },
193 | },
194 | },
195 | }),
196 | [yMax]
197 | );
198 |
199 | return (
200 | <>
201 |
202 |
203 | >
204 | );
205 | };
206 |
207 | DynamicOptions.args = {
208 | data: multitypeChart.data,
209 | };
210 |
--------------------------------------------------------------------------------
/stories/Doughnut.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import 'chart.js/auto';
3 | import { Doughnut } from '../src';
4 | import { data } from '../sandboxes/doughnut/default/App';
5 |
6 | export default {
7 | title: 'Components/Doughnut',
8 | component: Doughnut,
9 | parameters: {
10 | layout: 'centered',
11 | },
12 | args: {
13 | width: 500,
14 | height: 400,
15 | },
16 | };
17 |
18 | export const Default = args => ;
19 |
20 | Default.args = {
21 | data,
22 | };
23 |
24 | export const Rotation = args => {
25 | const [rotation, setRotation] = useState(0);
26 |
27 | useEffect(() => {
28 | const interval = setInterval(() => {
29 | setRotation(rotation => rotation + 90);
30 | }, 3000);
31 |
32 | return () => clearInterval(interval);
33 | });
34 |
35 | return ;
36 | };
37 |
38 | Rotation.args = {
39 | data,
40 | };
41 |
--------------------------------------------------------------------------------
/stories/Line.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import 'chart.js/auto';
3 | import { Line } from '../src';
4 | import * as defaultLine from '../sandboxes/line/default/App';
5 | import * as multiaxisLine from '../sandboxes/line/multiaxis/App';
6 |
7 | export default {
8 | title: 'Components/Line',
9 | component: Line,
10 | parameters: {
11 | layout: 'centered',
12 | },
13 | args: {
14 | width: 500,
15 | height: 400,
16 | },
17 | };
18 |
19 | export const Default = args => ;
20 |
21 | Default.args = {
22 | data: defaultLine.data,
23 | options: defaultLine.options,
24 | };
25 |
26 | export const MultiAxis = args => ;
27 |
28 | MultiAxis.args = {
29 | data: multiaxisLine.data,
30 | options: multiaxisLine.options,
31 | };
32 |
--------------------------------------------------------------------------------
/stories/Pie.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import faker from 'faker';
3 | import 'chart.js/auto';
4 | import { Pie } from '../src';
5 | import { data } from '../sandboxes/pie/default/App';
6 |
7 | export default {
8 | title: 'Components/Pie',
9 | component: Pie,
10 | parameters: {
11 | layout: 'centered',
12 | },
13 | args: {
14 | width: 500,
15 | height: 400,
16 | },
17 | };
18 |
19 | export const Default = args => ;
20 |
21 | Default.args = {
22 | data,
23 | };
24 |
25 | function randomDataset() {
26 | return {
27 | value: faker.datatype.number({ min: -100, max: 100 }),
28 | color: faker.internet.color(),
29 | };
30 | }
31 |
32 | export const Dynamic = args => {
33 | const [datasets, setDatasets] = useState(() => [randomDataset()]);
34 | const onAdd = () => {
35 | setDatasets(datasets => [...datasets, randomDataset()]);
36 | };
37 | const onRemove = () => {
38 | setDatasets(datasets => datasets.slice(0, -1));
39 | };
40 | const data = {
41 | labels: datasets.map((_, i) => `#${i}`),
42 | datasets: [
43 | {
44 | data: datasets.map(({ value }) => value),
45 | backgroundColor: datasets.map(({ color }) => color),
46 | },
47 | ],
48 | };
49 |
50 | return (
51 | <>
52 |
53 |
54 |
55 |
56 | {datasets.map(({ value, color }, i) => (
57 | -
58 | {value}
59 |
60 | ))}
61 |
62 | >
63 | );
64 | };
65 |
--------------------------------------------------------------------------------
/stories/PolarArea.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import 'chart.js/auto';
3 | import { PolarArea } from '../src';
4 | import { data } from '../sandboxes/polarArea/default/App';
5 |
6 | export default {
7 | title: 'Components/PolarArea',
8 | component: PolarArea,
9 | parameters: {
10 | layout: 'centered',
11 | },
12 | args: {
13 | width: 500,
14 | height: 400,
15 | },
16 | };
17 |
18 | export const Default = args => ;
19 |
20 | Default.args = {
21 | data,
22 | };
23 |
--------------------------------------------------------------------------------
/stories/Radar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import 'chart.js/auto';
3 | import { Radar } from '../src';
4 | import { data } from '../sandboxes/radar/default/App';
5 |
6 | export default {
7 | title: 'Components/Radar',
8 | component: Radar,
9 | parameters: {
10 | layout: 'centered',
11 | },
12 | args: {
13 | width: 500,
14 | height: 400,
15 | },
16 | };
17 |
18 | export const Default = args => ;
19 |
20 | Default.args = {
21 | data,
22 | };
23 |
--------------------------------------------------------------------------------
/stories/Scatter.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import 'chart.js/auto';
3 | import { Scatter } from '../src';
4 | import { data, options } from '../sandboxes/scatter/default/App';
5 |
6 | export default {
7 | title: 'Components/Scatter',
8 | component: Scatter,
9 | parameters: {
10 | layout: 'centered',
11 | },
12 | args: {
13 | width: 500,
14 | height: 400,
15 | },
16 | };
17 |
18 | export const Default = args => ;
19 |
20 | Default.args = {
21 | data,
22 | options,
23 | };
24 |
--------------------------------------------------------------------------------
/stories/data.ts:
--------------------------------------------------------------------------------
1 | import faker from 'faker';
2 |
3 | export const months = [
4 | 'January',
5 | 'February',
6 | 'March',
7 | 'April',
8 | 'May',
9 | 'June',
10 | 'July',
11 | ];
12 | export const colorRed = 'rgb(255, 99, 132)';
13 | export const colorRed05 = 'rgba(255, 99, 132, 0.5)';
14 | export const colorGreen = 'rgb(75, 192, 192)';
15 | export const colorGreen05 = 'rgba(75, 192, 192, 0.5)';
16 | export const colorBlue = 'rgb(53, 162, 235)';
17 | export const colorBlue05 = 'rgba(53, 162, 235, 0.5)';
18 |
19 | export function numbers(count = months.length) {
20 | return Array.from({ length: count }, () =>
21 | faker.datatype.number({ min: -100, max: 100 })
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/test/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "@typescript-eslint/no-explicit-any": "off"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/test/chart.test-d.tsx:
--------------------------------------------------------------------------------
1 | import { expectError } from 'tsd';
2 | import React from 'react';
3 | import type { Plugin } from 'chart.js';
4 | import { Chart, Scatter, Doughnut } from '../src';
5 |
6 | const data = {
7 | datasets: [],
8 | };
9 | const multiTypeData = {
10 | datasets: [
11 | {
12 | type: 'line' as const,
13 | label: 'Dataset 1',
14 | data: [],
15 | },
16 | {
17 | type: 'bar' as const,
18 | label: 'Dataset 2',
19 | data: [],
20 | },
21 | ],
22 | };
23 |
24 | /**
25 | * Should check type-specific props
26 | */
27 |
28 | []} />;
29 | []} />;
30 | ;
31 | []} />;
32 |
33 | expectError([]} />);
34 |
35 | /**
36 | * Should check type-specific options
37 | */
38 |
39 | ;
45 |
46 | expectError(
47 |
53 | );
54 |
--------------------------------------------------------------------------------
/test/chart.test.tsx:
--------------------------------------------------------------------------------
1 | import { vi, beforeEach, afterEach, describe, it, expect } from 'vitest';
2 | import React from 'react';
3 | import { render, cleanup, fireEvent } from '@testing-library/react';
4 | import 'chart.js/auto';
5 | import { Chart as ChartJS } from 'chart.js';
6 | import { Chart } from '../src/index.js';
7 |
8 | describe('', () => {
9 | const data = {
10 | labels: ['red', 'blue'],
11 | datasets: [{ label: 'colors', data: [1, 2] }],
12 | };
13 |
14 | const options = {
15 | responsive: false,
16 | };
17 |
18 | let chart: any, update: any, destroy: any;
19 | const ref = (el: ChartJS | undefined | null): void => {
20 | chart = el;
21 |
22 | if (chart) {
23 | update = vi.spyOn(chart, 'update');
24 | destroy = vi.spyOn(chart, 'destroy');
25 | }
26 | };
27 |
28 | beforeEach(() => {
29 | chart = null;
30 | });
31 |
32 | afterEach(() => {
33 | if (chart) chart.destroy();
34 |
35 | cleanup();
36 |
37 | if (update) update.mockClear();
38 | if (destroy) destroy.mockClear();
39 | });
40 |
41 | it('should not pollute props', () => {
42 | render();
43 |
44 | expect(data).toStrictEqual({
45 | labels: ['red', 'blue'],
46 | datasets: [{ label: 'colors', data: [1, 2] }],
47 | });
48 |
49 | // expect(options).toStrictEqual({
50 | // responsive: false,
51 | // });
52 | });
53 |
54 | it('should set ref to chart instance', () => {
55 | render();
56 |
57 | expect(chart).toBeTruthy();
58 | expect(chart instanceof ChartJS).toBe(true);
59 | });
60 |
61 | it('should pass props onto chart', () => {
62 | render();
63 |
64 | expect(chart.config.data).toMatchObject(data);
65 | expect(chart.config.options).toMatchObject(options);
66 | expect(chart.config.type).toEqual('bar');
67 | });
68 |
69 | it('should pass new data on data change', () => {
70 | const newData = {
71 | labels: ['red', 'blue'],
72 | datasets: [{ label: 'colors', data: [2, 1] }],
73 | };
74 |
75 | const { rerender } = render(
76 |
77 | );
78 |
79 | // const meta = chart.config.data.datasets[0]._meta;
80 | const id = chart.id;
81 |
82 | rerender();
83 |
84 | expect(chart.config.data).toMatchObject(newData);
85 | // make sure that other properties were maintained
86 | // expect(chart.config.data.datasets[0]._meta).toEqual(meta);
87 | expect(update).toHaveBeenCalled();
88 | expect(chart.id).toEqual(id);
89 | });
90 |
91 | it('should properly update with entirely new data', () => {
92 | const newData = {
93 | labels: ['purple', 'pink'],
94 | datasets: [{ label: 'new-colors', data: [1, 10] }],
95 | };
96 |
97 | const { rerender } = render(
98 |
99 | );
100 |
101 | const meta = chart.config.data.datasets[0]._meta;
102 | const id = chart.id;
103 |
104 | rerender();
105 |
106 | expect(chart.config.data).toMatchObject(newData);
107 | expect(meta).not.toEqual(chart.config.data.datasets[0]);
108 | expect(update).toHaveBeenCalled();
109 | expect(chart.id).toEqual(id);
110 | });
111 |
112 | it('should properly update with a new chart type', () => {
113 | const newType = 'line';
114 |
115 | const { rerender } = render(
116 |
117 | );
118 |
119 | const originalChartDestroy = destroy;
120 |
121 | rerender();
122 |
123 | expect(originalChartDestroy).toHaveBeenCalled();
124 | });
125 |
126 | it('should properly maintain order with new data', () => {
127 | const oldData = {
128 | labels: ['red', 'blue'],
129 | datasets: [
130 | { label: 'new-colors', data: [1, 2] },
131 | { label: 'colors', data: [3, 2] },
132 | ],
133 | };
134 |
135 | const newData = {
136 | labels: ['red', 'blue'],
137 | datasets: [
138 | { label: 'colors', data: [4, 5] },
139 | { label: 'new-colors', data: [1, 2] },
140 | ],
141 | };
142 |
143 | const { rerender } = render(
144 |
145 | );
146 |
147 | const meta = Object.assign({}, chart._metasets);
148 |
149 | const id = chart.id;
150 |
151 | rerender();
152 |
153 | expect(chart.config.data).toMatchObject(newData);
154 | expect(meta[0]).toBe(chart._metasets[1]);
155 | expect(meta[1]).toBe(chart._metasets[0]);
156 | expect(update).toHaveBeenCalled();
157 | expect(chart.id).toEqual(id);
158 | });
159 |
160 | it('should properly update when original data did not exist', () => {
161 | const oldData = {
162 | labels: ['red', 'blue'],
163 | datasets: [
164 | { label: 'new-colors', data: [] },
165 | { label: 'colors', data: [3, 2] },
166 | ],
167 | };
168 |
169 | const newData = {
170 | labels: ['red', 'blue'],
171 | datasets: [
172 | { label: 'colors', data: [4, 5] },
173 | { label: 'new-colors', data: [1, 2] },
174 | ],
175 | };
176 |
177 | const { rerender } = render(
178 |
179 | );
180 |
181 | // even when we feed the data as undefined, the constructor will
182 | // force it to []. Here we force it back
183 | chart.config.data.datasets[0].data = undefined;
184 | const meta = Object.assign({}, chart._metasets);
185 |
186 | const id = chart.id;
187 |
188 | rerender();
189 |
190 | expect(chart.config.data).toMatchObject(newData);
191 | expect(meta[0]).toBe(chart._metasets[1]);
192 | expect(update).toHaveBeenCalled();
193 | expect(chart.id).toEqual(id);
194 | });
195 |
196 | it('should properly update when incoming data does not exist', () => {
197 | const oldData = {
198 | labels: ['red', 'blue'],
199 | datasets: [
200 | { label: 'new-colors', data: [1, 2] },
201 | { label: 'colors', data: [3, 2] },
202 | ],
203 | };
204 |
205 | const newData = {
206 | labels: ['red', 'blue'],
207 | datasets: [
208 | { label: 'colors', data: [4, 5] },
209 | { label: 'new-colors', data: [] },
210 | ],
211 | };
212 |
213 | const { rerender } = render(
214 |
215 | );
216 |
217 | const id = chart.id;
218 |
219 | rerender();
220 |
221 | expect(chart.config.data).toMatchObject(newData);
222 | expect(update).toHaveBeenCalled();
223 | expect(chart.id).toEqual(id);
224 | });
225 |
226 | it('should pass new options on options change', () => {
227 | const newOptions = {
228 | responsive: true,
229 | };
230 |
231 | const { rerender } = render(
232 |
233 | );
234 |
235 | const id = chart.id;
236 |
237 | rerender();
238 |
239 | expect(chart.options).toMatchObject(newOptions);
240 | expect(update).toHaveBeenCalled();
241 | expect(chart.id).toEqual(id);
242 | });
243 |
244 | it('should destroy and rerender when set to redraw', () => {
245 | const newData = {
246 | labels: ['red', 'blue'],
247 | datasets: [{ label: 'colors', data: [2, 1] }],
248 | };
249 |
250 | const { rerender } = render(
251 |
252 | );
253 |
254 | // const id = chart.id;
255 | const originalChartDestroy = destroy;
256 |
257 | rerender(
258 |
259 | );
260 |
261 | expect(originalChartDestroy).toHaveBeenCalled();
262 | });
263 |
264 | it('should destroy when unmounted', () => {
265 | const { unmount } = render(
266 |
267 | );
268 |
269 | expect(chart).toBeTruthy();
270 |
271 | unmount();
272 |
273 | expect(chart).toBe(null);
274 | });
275 |
276 | it('should add className ', () => {
277 | render(
278 |
285 | );
286 |
287 | expect(chart).toBeTruthy();
288 | expect(chart.canvas).toHaveProperty('className');
289 | expect(chart.canvas).toHaveClass('chart-example');
290 | });
291 |
292 | it('should call onClick', () => {
293 | const onClick = vi.fn();
294 |
295 | const { getByTestId } = render(
296 |
304 | );
305 |
306 | fireEvent.click(getByTestId('canvas'));
307 |
308 | expect(onClick).toHaveBeenCalled();
309 | });
310 |
311 | it('should show fallback content if given', () => {
312 | const fallback = Fallback content
;
313 | const { getByTestId } = render(
314 |
322 | );
323 |
324 | expect(chart).toBeTruthy();
325 | expect(chart.canvas).toContainElement(getByTestId('fallbackContent'));
326 | });
327 |
328 | it('should pass through aria labels to the canvas element', () => {
329 | const ariaLabel = 'ARIA LABEL';
330 | render(
331 |
338 | );
339 |
340 | expect(chart.canvas.getAttribute('aria-label')).toBe(ariaLabel);
341 | });
342 |
343 | it('should rerender datasets with same labels', () => {
344 | const getData = () => ({
345 | labels: [1, 2, 3],
346 | datasets: [
347 | {
348 | label: '',
349 | data: [5, 6, 7],
350 | },
351 | {
352 | label: '',
353 | data: [3, 2, 1],
354 | },
355 | ],
356 | });
357 |
358 | const { rerender } = render(
359 |
360 | );
361 |
362 | const [prevDataset1, prevDataset2] = chart.config.data.datasets;
363 |
364 | rerender();
365 |
366 | const [nextDataset1, nextDataset2] = chart.config.data.datasets;
367 |
368 | expect(prevDataset1).toBe(nextDataset1);
369 | expect(prevDataset2).not.toBe(nextDataset2);
370 | });
371 |
372 | it('should rerender datasets with id', () => {
373 | const getData = () => ({
374 | labels: [1, 2, 3],
375 | datasets: [
376 | {
377 | id: 1,
378 | label: '',
379 | data: [5, 6, 7],
380 | },
381 | {
382 | id: 2,
383 | label: '',
384 | data: [3, 2, 1],
385 | },
386 | ],
387 | });
388 |
389 | const { rerender } = render(
390 |
391 | );
392 |
393 | const [prevDataset1, prevDataset2] = chart.config.data.datasets;
394 |
395 | rerender(
396 |
397 | );
398 |
399 | const [nextDataset1, nextDataset2] = chart.config.data.datasets;
400 |
401 | expect(prevDataset1).toBe(nextDataset1);
402 | expect(prevDataset2).toBe(nextDataset2);
403 | });
404 |
405 | it('should pass updateMode prop to update method', () => {
406 | const newData = {
407 | labels: ['purple', 'pink'],
408 | datasets: [{ label: 'new-colors', data: [1, 10] }],
409 | };
410 |
411 | const { rerender } = render(
412 |
419 | );
420 |
421 | rerender(
422 |
429 | );
430 |
431 | expect(update).toHaveBeenCalledTimes(1);
432 | expect(update).toBeCalledWith('active');
433 | });
434 | });
435 |
--------------------------------------------------------------------------------
/test/setup.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import matchers from '@testing-library/jest-dom/matchers';
3 | import { expect } from 'vitest';
4 | import 'vitest-canvas-mock';
5 |
6 | expect.extend(matchers);
7 |
8 | class ResizeObserver {
9 | observe() {}
10 | unobserve() {}
11 | disconnect() {}
12 | }
13 |
14 | window.ResizeObserver = ResizeObserver;
15 |
16 | class MutationObserver {
17 | disconnect() {}
18 | unobserve() {}
19 | observe() {}
20 | }
21 |
22 | window.MutationObserver = MutationObserver;
23 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Type Checking */
4 | "strict": true,
5 | "strictBindCallApply": true,
6 | "noFallthroughCasesInSwitch": true,
7 | "noImplicitOverride": true,
8 | "noImplicitReturns": true,
9 | "noUnusedLocals": true,
10 | "noUnusedParameters": true,
11 | /* Modules */
12 | "baseUrl": ".",
13 | "module": "ESNext",
14 | "moduleResolution": "NodeNext",
15 | "resolveJsonModule": true,
16 | /* Emit */
17 | "declaration": true,
18 | "declarationMap": true,
19 | "importsNotUsedAsValues": "error",
20 | "inlineSourceMap": true,
21 | "outDir": "dist",
22 | /* Interop Constraints */
23 | "allowSyntheticDefaultImports": true,
24 | "isolatedModules": true,
25 | /* Language and Environment */
26 | "jsx": "react",
27 | "lib": [
28 | "dom",
29 | "esnext"
30 | ],
31 | "target": "ESNext",
32 | /* Completeness */
33 | "skipLibCheck": true
34 | },
35 | "include": [
36 | "src"
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | test: {
7 | environment: 'jsdom',
8 | setupFiles: ['test/setup.js'],
9 | deps: {
10 | inline: ['vitest-canvas-mock'],
11 | },
12 | coverage: {
13 | reporter: ['lcovonly', 'text'],
14 | },
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/website/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.*
14 |
15 | npm-debug.log*
16 |
--------------------------------------------------------------------------------
/website/CNAME:
--------------------------------------------------------------------------------
1 | react-chartjs-2.js.org
2 |
--------------------------------------------------------------------------------
/website/README.md:
--------------------------------------------------------------------------------
1 | # Website
2 |
3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4 |
5 | ### Installation
6 |
7 | ```
8 | $ pnpm install
9 | ```
10 |
11 | ### Local Development
12 |
13 | ```
14 | $ pnpm start
15 | ```
16 |
17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18 |
19 | ### Build
20 |
21 | ```
22 | $ pnpm build
23 | ```
24 |
25 | This command generates static content into the `build` directory and can be served using any static contents hosting service.
26 |
27 | ### Deployment
28 |
29 | ```
30 | $ GIT_USER= USE_SSH=true pnpm deploy
31 | ```
32 |
33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
34 |
--------------------------------------------------------------------------------
/website/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3 | };
4 |
--------------------------------------------------------------------------------
/website/docs/chartjs-v2.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | slug: /docs/chartjs-v2
3 | description: Using react-chartjs-2 with Chart.js v2
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 | # Using with Chart.js v2
10 |
11 | If your app needs [Chart.js v2](https://www.chartjs.org/docs/2.9.4/), please use a [compatible version](https://www.npmjs.com/package/react-chartjs-2/v/2.11.2) of this library:
12 |
13 |
14 |
15 |
16 | ```bash
17 | yarn add chart.js@^2.9.4 react-chartjs-2@^2.11.2
18 | ```
19 |
20 |
21 |
22 |
23 | ```bash
24 | pnpm add chart.js@^2.9.4 react-chartjs-2@^2.11.2
25 | ```
26 |
27 |
28 |
29 |
30 | ```bash
31 | npm install --save chart.js@^2.9.4 react-chartjs-2@^2.11.2
32 | ```
33 |
34 |
35 |
36 |
37 | Also, please consider upgrading your app to [Chart.js v3](#upgrading-to-chartjs-v3).
38 |
39 | ## Upgrading to Chart.js v3
40 |
41 | First, upgrade packages. You'll need to install Chart.js v3 and the latest version of this library:
42 |
43 |
44 |
45 |
46 | ```bash
47 | yarn add chart.js@^3.6.0 react-chartjs-2@^4.0.0
48 | ```
49 |
50 |
51 |
52 |
53 | ```bash
54 | pnpm add chart.js@^3.6.0 react-chartjs-2@^4.0.0
55 | ```
56 |
57 |
58 |
59 |
60 | ```bash
61 | npm install --save chart.js@^3.6.0 react-chartjs-2@^4.0.0
62 | ```
63 |
64 |
65 |
66 |
67 | Then, please follow the [this guide](/docs/migration-to-v4).
68 |
--------------------------------------------------------------------------------
/website/docs/chartjs-v3.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | slug: /docs/chartjs-v3
3 | description: Using react-chartjs-2 with Chart.js v3
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 | # Using with Chart.js v3
10 |
11 | If your app needs [Chart.js v3](https://www.chartjs.org/docs/3.9.1/), please use a [compatible version](https://www.npmjs.com/package/react-chartjs-2/v/4.3.1) of this library:
12 |
13 |
14 |
15 |
16 | ```bash
17 | yarn add chart.js@^3.9.1 react-chartjs-2@^4.3.1
18 | ```
19 |
20 |
21 |
22 |
23 | ```bash
24 | pnpm add chart.js@^3.9.1 react-chartjs-2@^4.3.1
25 | ```
26 |
27 |
28 |
29 |
30 | ```bash
31 | npm install --save chart.js@^3.9.1 react-chartjs-2@^4.3.1
32 | ```
33 |
34 |
35 |
36 |
37 | Also, please consider upgrading your app to [Chart.js v3](#upgrading-to-chartjs-v3).
38 |
39 | ## Upgrading to Chart.js v4
40 |
41 | First, upgrade packages. You'll need to install Chart.js v3 and the latest version of this library:
42 |
43 |
44 |
45 |
46 | ```bash
47 | yarn add chart.js@^4.0.0 react-chartjs-2@^5.0.0
48 | ```
49 |
50 |
51 |
52 |
53 | ```bash
54 | pnpm add chart.js@^4.0.0 react-chartjs-2@^5.0.0
55 | ```
56 |
57 |
58 |
59 |
60 | ```bash
61 | npm install --save chart.js@^4.0.0 react-chartjs-2@^5.0.0
62 | ```
63 |
64 |
65 |
66 |
67 | Then, please follow the [this guide](/docs/migration-to-v5).
68 |
--------------------------------------------------------------------------------
/website/docs/components/bar.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | description: Description of Bar component from react-chartjs-2.
3 | ---
4 |
5 | import PropsTable from '../../src/components/PropsTable'
6 |
7 | # Bar
8 |
9 | ## Usage
10 |
11 | ```jsx
12 | import { Bar } from 'react-chartjs-2';
13 |
14 |
19 | ```
20 |
21 | [See full usage examples.](/tags/bar-chart)
22 |
23 | ## Props
24 |
25 | Also supports all standard `