├── .editorconfig
├── .eslintrc
├── .gitattributes
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .prettierrc
├── .vs
├── React-HighCharts
│ └── v17
│ │ └── .suo
├── VSWorkspaceState.json
└── slnx.sqlite
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── babel.config.js
├── index.html
├── package-lock.json
├── package.json
└── packages
├── react-jsx-highcharts
├── .babelrc
├── README.md
├── jest.config.js
├── package.json
├── src
│ ├── components
│ │ ├── Annotation
│ │ │ ├── Annotation.js
│ │ │ └── index.js
│ │ ├── Axis
│ │ │ ├── Axis.js
│ │ │ ├── AxisTitle.js
│ │ │ ├── createProvidedAxis.js
│ │ │ └── index.js
│ │ ├── AxisContext
│ │ │ └── index.js
│ │ ├── BarSeries
│ │ │ ├── BarSeries.js
│ │ │ └── index.js
│ │ ├── BaseChart
│ │ │ ├── BaseChart.js
│ │ │ ├── createProvidedChart.js
│ │ │ └── index.js
│ │ ├── Caption
│ │ │ ├── Caption.js
│ │ │ └── index.js
│ │ ├── Chart
│ │ │ ├── Chart.js
│ │ │ └── index.js
│ │ ├── ChartContext
│ │ │ └── index.js
│ │ ├── ColorAxis
│ │ │ ├── ColorAxis.js
│ │ │ ├── createProvidedColorAxis.js
│ │ │ └── index.js
│ │ ├── ColorAxisContext
│ │ │ └── index.js
│ │ ├── Credits
│ │ │ ├── Credits.js
│ │ │ └── index.js
│ │ ├── Debug
│ │ │ ├── Debug.js
│ │ │ └── index.js
│ │ ├── Highcharts3dChart
│ │ │ ├── Highcharts3dChart.js
│ │ │ └── index.js
│ │ ├── HighchartsChart
│ │ │ ├── HighchartsChart.js
│ │ │ └── index.js
│ │ ├── HighchartsContext
│ │ │ └── index.js
│ │ ├── HighchartsSparkline
│ │ │ ├── HighchartsSparkline.js
│ │ │ └── index.js
│ │ ├── Legend
│ │ │ ├── Legend.js
│ │ │ ├── LegendTitle.js
│ │ │ └── index.js
│ │ ├── Loading
│ │ │ ├── Loading.js
│ │ │ └── index.js
│ │ ├── Options3d
│ │ │ ├── Options3d.js
│ │ │ └── index.js
│ │ ├── Pane
│ │ │ ├── Pane.js
│ │ │ └── index.js
│ │ ├── PlotBandLine
│ │ │ ├── PlotBand.js
│ │ │ ├── PlotBandLineLabel.js
│ │ │ ├── PlotLine.js
│ │ │ ├── UsePlotBandLineLifecycle.js
│ │ │ └── index.js
│ │ ├── PlotBandLineContext
│ │ │ └── index.js
│ │ ├── Series
│ │ │ ├── Series.js
│ │ │ ├── createProvidedSeries.js
│ │ │ └── index.js
│ │ ├── SeriesContext
│ │ │ └── index.js
│ │ ├── Subtitle
│ │ │ ├── Subtitle.js
│ │ │ └── index.js
│ │ ├── Title
│ │ │ ├── Title.js
│ │ │ └── index.js
│ │ ├── Tooltip
│ │ │ ├── Tooltip.js
│ │ │ └── index.js
│ │ ├── UseAxis
│ │ │ └── index.js
│ │ ├── UseChart
│ │ │ └── index.js
│ │ ├── UseChartUpdate
│ │ │ └── index.js
│ │ ├── UseColorAxis
│ │ │ └── index.js
│ │ ├── UseHighcharts
│ │ │ └── index.js
│ │ ├── UseManualEventHandlers
│ │ │ └── index.js
│ │ ├── UseModifiedProps
│ │ │ └── index.js
│ │ ├── UsePlotBandLine
│ │ │ └── index.js
│ │ ├── UsePrevious
│ │ │ └── index.js
│ │ ├── UseSeries
│ │ │ └── index.js
│ │ ├── WithHighcharts
│ │ │ └── index.js
│ │ ├── WithSeriesType
│ │ │ └── index.js
│ │ ├── XAxis
│ │ │ ├── XAxis.js
│ │ │ └── index.js
│ │ ├── YAxis
│ │ │ ├── YAxis.js
│ │ │ └── index.js
│ │ └── ZAxis
│ │ │ ├── ZAxis.js
│ │ │ └── index.js
│ ├── index.js
│ └── utils
│ │ ├── debounce-raf.js
│ │ ├── events.js
│ │ ├── getModifiedProps.js
│ │ ├── pickBy.js
│ │ └── warnings.js
├── test
│ ├── .eslintrc
│ ├── ContextSpy.js
│ ├── components
│ │ ├── Annotation
│ │ │ └── Annotation.spec.js
│ │ ├── Axis
│ │ │ ├── Axis.integration.spec.js
│ │ │ ├── Axis.spec.js
│ │ │ └── AxisTitle.spec.js
│ │ ├── BarSeries
│ │ │ └── BarSeries.spec.js
│ │ ├── BaseChart
│ │ │ └── BaseChart.spec.js
│ │ ├── Caption
│ │ │ └── Caption.spec.js
│ │ ├── Chart
│ │ │ └── Chart.spec.js
│ │ ├── ColorAxis
│ │ │ └── ColorAxis.integration.spec.js
│ │ ├── Credits
│ │ │ └── Credits.spec.js
│ │ ├── HighchartsChart
│ │ │ └── HighchartsChart.spec.js
│ │ ├── Legend
│ │ │ ├── Legend.spec.js
│ │ │ └── LegendTitle.spec.js
│ │ ├── Loading
│ │ │ └── Loading.spec.js
│ │ ├── Options3d
│ │ │ └── Options3d.spec.js
│ │ ├── Pane
│ │ │ └── Pane.spec.js
│ │ ├── PlotBandLine
│ │ │ ├── PlotBand.integration.spec.js
│ │ │ ├── PlotBandLineLabel.integration.spec.js
│ │ │ ├── PlotBandLineLabel.spec.js
│ │ │ └── PlotLine.spec.js
│ │ ├── Series
│ │ │ ├── Series.integration.spec.js
│ │ │ ├── Series.spec.js
│ │ │ ├── SeriesTypes.integration.spec.js
│ │ │ └── SeriesTypes.spec.js
│ │ ├── Subtitle
│ │ │ └── Subtitle.spec.js
│ │ ├── Title
│ │ │ └── Title.spec.js
│ │ ├── Tooltip
│ │ │ └── Tooltip.spec.js
│ │ ├── UseAxis
│ │ │ └── useAxis.spec.js
│ │ ├── UseChart
│ │ │ └── useChart.spec.js
│ │ ├── UseChartUpdate
│ │ │ └── useChartUpdate.spec.js
│ │ ├── UseHighcharts
│ │ │ └── useHighcharts.spec.js
│ │ ├── UseManualEventHandlers
│ │ │ └── useManualEventHandlers.spec.js
│ │ ├── UseModifiedProps
│ │ │ └── useModifiedProps.spec.js
│ │ ├── UsePlotBandLine
│ │ │ └── usePlotBandLine.spec.js
│ │ ├── UseSeries
│ │ │ └── useSeries.spec.js
│ │ ├── WithHighcharts
│ │ │ └── index.spec.js
│ │ ├── WithSeriesType
│ │ │ └── index.spec.js
│ │ ├── XAxis
│ │ │ └── XAxis.spec.js
│ │ ├── YAxis
│ │ │ └── YAxis.spec.js
│ │ └── ZAxis
│ │ │ └── ZAxis.spec.js
│ ├── test-helper.js
│ ├── test-utils.js
│ └── utils
│ │ ├── events.spec.js
│ │ ├── getModifiedProps.spec.js
│ │ ├── pickBy.spec.js
│ │ └── warnings.spec.js
├── tsconfig.json
├── types
│ └── index.d.ts
└── webpack.config.js
├── react-jsx-highmaps
├── .babelrc
├── README.md
├── jest.config.js
├── package.json
├── src
│ ├── components
│ │ ├── HighchartsMapChart
│ │ │ ├── HighchartsMapChart.js
│ │ │ └── index.js
│ │ ├── MapNavigation
│ │ │ ├── MapNavigation.js
│ │ │ ├── MapNavigationButton.js
│ │ │ ├── MapNavigationZoomIn.js
│ │ │ ├── MapNavigationZoomOut.js
│ │ │ └── index.js
│ │ ├── XAxis
│ │ │ ├── XAxis.js
│ │ │ └── index.js
│ │ └── YAxis
│ │ │ ├── YAxis.js
│ │ │ └── index.js
│ └── index.js
├── test
│ ├── .eslintrc
│ ├── components
│ │ ├── HighchartsMapChart
│ │ │ └── HighchartsMapChart.spec.js
│ │ ├── XAxis
│ │ │ └── XAxis.spec.js
│ │ └── YAxis
│ │ │ └── YAxis.spec.js
│ ├── test-helper.js
│ └── test-utils.js
├── tsconfig.json
├── types
│ └── index.d.ts
└── webpack.config.js
└── react-jsx-highstock
├── .babelrc
├── README.md
├── jest.config.js
├── package.json
├── src
├── components
│ ├── HighchartsStockChart
│ │ ├── HighchartsStockChart.js
│ │ └── index.js
│ ├── Navigator
│ │ ├── Navigator.js
│ │ ├── NavigatorAxis.js
│ │ ├── NavigatorSeries.js
│ │ ├── NavigatorXAxis.js
│ │ ├── NavigatorYAxis.js
│ │ └── index.js
│ ├── RangeSelector
│ │ ├── RangeSelector.js
│ │ ├── RangeSelectorButton.js
│ │ ├── RangeSelectorInput.js
│ │ └── index.js
│ └── Scrollbar
│ │ ├── Scrollbar.js
│ │ └── index.js
└── index.js
├── test
├── .eslintrc
├── components
│ ├── HighchartsStockChart
│ │ └── HighchartsStockChart.spec.js
│ ├── Navigator
│ │ ├── Navigator.integration.spec.js
│ │ ├── Navigator.spec.js
│ │ └── NavigatorXAxis.integration.spec.js
│ ├── RangeSelector
│ │ ├── RangeSelector.spec.js
│ │ └── RangeSelectorInput.spec.js
│ └── Scrollbar
│ │ └── Scrollbar.spec.js
├── test-helper.js
└── test-utils.js
├── tsconfig.json
├── types
└── index.d.ts
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | # A special property that should be specified at the top of the file outside of
4 | # any sections. Set to true to stop .editor config file search on current file
5 | root = true
6 |
7 | [*]
8 | # Indentation style
9 | # Possible values - tab, space
10 | indent_style = space
11 |
12 | # Indentation size in single-spaced characters
13 | # Possible values - an integer, tab
14 | indent_size = 2
15 |
16 | # Line ending file format
17 | # Possible values - lf, crlf, cr
18 | end_of_line = lf
19 |
20 | # File character encoding
21 | # Possible values - latin1, utf-8, utf-16be, utf-16le
22 | charset = utf-8
23 |
24 | # Denotes whether to trim whitespace at the end of lines
25 | # Possible values - true, false
26 | trim_trailing_whitespace = true
27 |
28 | # Denotes whether file should end with a newline
29 | # Possible values - true, false
30 | insert_final_newline = true
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@babel/eslint-parser",
4 | "plugins": ["react", "import", "react-hooks", "react-perf", "prettier"],
5 | "settings": {
6 | "react": {
7 | "version": "detect"
8 | }
9 | },
10 | "parserOptions": {
11 | "ecmaVersion": "latest",
12 | "sourceType": "module",
13 | "ecmaFeatures": {
14 | "jsx": true
15 | }
16 | },
17 | "env": {
18 | "browser": true,
19 | "es6": true
20 | },
21 | "extends": [
22 | "eslint:recommended",
23 | "plugin:react/recommended",
24 | "plugin:import/errors",
25 | "plugin:react-perf/recommended",
26 | "plugin:prettier/recommended"
27 | ],
28 | "rules": {
29 | "no-unused-vars": ["error", { "ignoreRestSiblings": true }],
30 | "react/prop-types": "off",
31 | "prefer-object-spread": "warn",
32 | "react-hooks/rules-of-hooks": "error",
33 | "react/jsx-no-constructed-context-values": "error"
34 | },
35 | "globals": {
36 | "process": false
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf whitespace=
2 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: test
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | types: [opened, synchronize]
8 |
9 | jobs:
10 | test:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 |
16 | - name: Setup Node
17 | uses: actions/setup-node@v3
18 | with:
19 | node-version: lts/*
20 | cache: 'npm'
21 |
22 | - name: Install dependencies
23 | run: npm ci
24 |
25 | - name: Build
26 | run: npm run build:prod
27 |
28 | - name: Lint
29 | run: npm run lint
30 |
31 | - name: Test
32 | run: npm run test:coverage
33 |
34 | - name: Upload coverage
35 | uses: codecov/codecov-action@v2
36 |
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # Editors
61 | .idea
62 |
63 | # react-jsx-highcharts
64 | dist
65 | /examples/*/bundle.js
66 | /examples/*/index.html
67 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "tabWidth": 2,
4 | "trailingComma": "none",
5 | "arrowParens": "avoid",
6 | "endOfLine": "auto"
7 | }
8 |
--------------------------------------------------------------------------------
/.vs/React-HighCharts/v17/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ITopGun/React-HighCharts/4b3d9dd6d051e1bfbd8de1ce0fd01583983db3a3/.vs/React-HighCharts/v17/.suo
--------------------------------------------------------------------------------
/.vs/VSWorkspaceState.json:
--------------------------------------------------------------------------------
1 | {
2 | "ExpandedNodes": [
3 | ""
4 | ],
5 | "PreviewInSolutionExplorer": false
6 | }
--------------------------------------------------------------------------------
/.vs/slnx.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ITopGun/React-HighCharts/4b3d9dd6d051e1bfbd8de1ce0fd01583983db3a3/.vs/slnx.sqlite
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | #### Bug or Feature Request?
2 |
3 |
4 | #### Description
5 |
6 |
7 | #### How to reproduce
8 |
9 |
10 | #### Live demo demonstrating bug
11 |
12 |
13 | #### Versions
14 | * React JSX Highcharts version:
15 | * Highcharts version:
16 | * React version:
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Will Hawker
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 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const ENV = process.env.BABEL_ENV || process.env.NODE_ENV || 'development';
3 |
4 | let config = {
5 | plugins: [],
6 | presets: [
7 | [
8 | '@babel/env',
9 | { modules: ENV === 'test' ? 'commonjs' : false, bugfixes: true }
10 | ],
11 | ['@babel/react', { runtime: ENV === 'es' ? 'automatic' : 'classic' }]
12 | ]
13 | };
14 |
15 | module.exports = config;
16 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | React Highcharts JSX
7 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "build:prod": "npm run build:prod --workspaces",
5 | "build:jsx-highcharts": "npm run build:prod --workspace packages/react-jsx-highcharts",
6 | "lint": "eslint \"packages/*/+(src|test)/**\"",
7 | "test": "npm run build:jsx-highcharts && jest",
8 | "test:coverage": "npm run build:jsx-highcharts && jest --coverage",
9 | "test:watch": "jest --watch"
10 | },
11 | "devDependencies": {
12 | "@babel/cli": "^7.19.3",
13 | "@babel/core": "^7.20.5",
14 | "@babel/eslint-parser": "^7.19.1",
15 | "@babel/preset-env": "^7.20.2",
16 | "@babel/preset-react": "^7.18.6",
17 | "@testing-library/react": "^13.4.0",
18 | "@types/react": "^18.0.26",
19 | "babel-loader": "^9.1.0",
20 | "cross-env": "^7.0.3",
21 | "eslint": "^8.29.0",
22 | "eslint-config-prettier": "^8.5.0",
23 | "eslint-plugin-import": "^2.26.0",
24 | "eslint-plugin-prettier": "^4.2.1",
25 | "eslint-plugin-react": "^7.31.11",
26 | "eslint-plugin-react-hooks": "^4.5.0",
27 | "eslint-plugin-react-perf": "^3.3.1",
28 | "highcharts": "^10.3.2",
29 | "jest": "^29.3.1",
30 | "jest-environment-jsdom": "^29.3.1",
31 | "prettier": "^2.8.1",
32 | "react": "^18.2.0",
33 | "react-dom": "^18.2.0",
34 | "react-test-renderer": "^18.2.0",
35 | "rimraf": "^3.0.2",
36 | "typescript": "^4.9.4",
37 | "webpack": "^5.75.0",
38 | "webpack-cli": "^5.0.1"
39 | },
40 | "workspaces": {
41 | "packages": [
42 | "packages/react-jsx-highcharts",
43 | "packages/react-jsx-highstock",
44 | "packages/react-jsx-highmaps"
45 | ]
46 | },
47 | "jest": {
48 | "projects": [
49 | "/packages/*"
50 | ]
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/.babelrc:
--------------------------------------------------------------------------------
1 | { "extends": "../../babel.config.js" }
2 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/jest.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | // For a detailed explanation regarding each configuration property, visit:
3 | // https://jestjs.io/docs/en/configuration.html
4 |
5 | /** @type {import('@jest/types').Config.InitialOptions} */
6 | const config = {
7 | testEnvironment: 'jsdom',
8 | setupFilesAfterEnv: ['/test/test-helper.js'],
9 | testMatch: ['**/test/**/*.spec.js?(x)']
10 | };
11 |
12 | module.exports = config;
13 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-jsx-highcharts",
3 | "version": "5.0.0",
4 | "description": "Highcharts charts built using React components",
5 | "main": "dist/react-jsx-highcharts.min.js",
6 | "module": "dist/es/index.js",
7 | "types": "types/index.d.ts",
8 | "sideEffects": false,
9 | "files": [
10 | "dist",
11 | "src",
12 | "types"
13 | ],
14 | "scripts": {
15 | "build": "cross-env NODE_ENV=development webpack",
16 | "build:prod": "npm run build:umd && npm run build:es",
17 | "build:umd": "cross-env NODE_ENV=production webpack",
18 | "build:es": "cross-env BABEL_ENV=es babel src --out-dir dist/es",
19 | "clean": "rimraf dist",
20 | "format": "prettier --write \"src/**/*.js\" \"test/**/*.js\" README.md \"../../README.md\"",
21 | "lint": "eslint src",
22 | "test": "jest",
23 | "test:coverage": "jest --coverage",
24 | "test:types": "tsc --noEmit"
25 | },
26 | "author": "Will Hawker",
27 | "contributors": [
28 | {
29 | "name": "Alex Mayants",
30 | "url": "https://github.com/AlexMayants"
31 | },
32 | {
33 | "name": "mrawdon",
34 | "url": "https://github.com/mrawdon"
35 | },
36 | {
37 | "name": "Ercan Akyürek",
38 | "url": "https://github.com/geforcefan"
39 | },
40 | {
41 | "name": "anajavi",
42 | "url": "https://github.com/anajavi"
43 | }
44 | ],
45 | "license": "MIT",
46 | "repository": {
47 | "type": "git",
48 | "url": "https://github.com/whawker/react-jsx-highcharts.git"
49 | },
50 | "bugs": "https://github.com/whawker/react-jsx-highcharts/issues",
51 | "homepage": "https://github.com/whawker/react-jsx-highcharts",
52 | "keywords": [
53 | "react",
54 | "reactjs",
55 | "react-component",
56 | "highcharts",
57 | "highstock",
58 | "chart",
59 | "charts",
60 | "graphs",
61 | "visualization",
62 | "data"
63 | ],
64 | "dependencies": {
65 | "uuid": "^9.0.0"
66 | },
67 | "peerDependencies": {
68 | "highcharts": "^9.1.2 || ^10.0.0",
69 | "react": "^17.0.0 || ^18.0.0",
70 | "react-dom": "^17.0.0 || ^18.0.0"
71 | },
72 | "browserslist": [
73 | "chrome >= 81",
74 | "edge >= 81",
75 | "firefox >= 78",
76 | "ios >= 12",
77 | "safari >= 12"
78 | ]
79 | }
80 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Annotation/Annotation.js:
--------------------------------------------------------------------------------
1 | import { useRef, useEffect, memo } from 'react';
2 | import { v4 as uuid } from 'uuid';
3 | import { logModuleErrorMessage } from '../../utils/warnings';
4 | import useChart from '../UseChart';
5 |
6 | const Annotation = memo(props => {
7 | const { id = uuid, children, ...rest } = props;
8 |
9 | const { addAnnotation, removeAnnotation } = useChart();
10 |
11 | if (process.env.NODE_ENV === 'development') {
12 | if (addAnnotation === null) {
13 | logModuleErrorMessage('', 'annotations');
14 | }
15 | }
16 |
17 | const idRef = useRef();
18 |
19 | useEffect(() => {
20 | idRef.current = typeof id === 'function' ? id() : id;
21 | const myId = idRef.current;
22 | const opts = {
23 | id: myId,
24 | ...rest
25 | };
26 | addAnnotation(opts);
27 |
28 | return () => {
29 | try {
30 | removeAnnotation(myId);
31 | } catch {
32 | // ignoring as parent chart might be unmounted
33 | }
34 | };
35 | });
36 |
37 | return null;
38 | });
39 |
40 | Annotation.displayName = 'Annotation';
41 |
42 | export default Annotation;
43 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Annotation/index.js:
--------------------------------------------------------------------------------
1 | import Annotation from './Annotation';
2 | export default Annotation;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Axis/Axis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useEffect, useState, useRef } from 'react';
3 | import { v4 as uuid } from 'uuid';
4 | import AxisContext from '../AxisContext';
5 | import { getNonEventHandlerProps, getEventsConfig } from '../../utils/events';
6 | import useModifiedProps from '../UseModifiedProps';
7 | import useChart from '../UseChart';
8 | import createProvidedAxis from './createProvidedAxis';
9 |
10 | const Axis = ({ children = null, dynamicAxis = true, ...restProps }) => {
11 | const chart = useChart();
12 | const axisRef = useRef(null);
13 | const providedAxisRef = useRef(null);
14 | const [hasAxis, setHasAxis] = useState(false);
15 |
16 | useEffect(() => {
17 | const axis = createAxis(chart, restProps, dynamicAxis);
18 | axisRef.current = axis;
19 | providedAxisRef.current = createProvidedAxis(axisRef.current);
20 | setHasAxis(true);
21 | chart.needsRedraw();
22 |
23 | return () => {
24 | if (axis.remove && dynamicAxis) {
25 | try {
26 | axis.remove.bind(axis)(false);
27 | } catch {
28 | // Axis may have already been removed, i.e. when Chart unmounted
29 | }
30 | chart.needsRedraw();
31 | }
32 | };
33 | }, []);
34 |
35 | const modifiedProps = useModifiedProps(restProps);
36 | useEffect(() => {
37 | if (!hasAxis) return;
38 | if (modifiedProps !== false) {
39 | const axis = axisRef.current;
40 | const nonEventProps = getNonEventHandlerProps(modifiedProps);
41 | const events = getEventsConfig(restProps); // update all events to be on safeside
42 | const updateProps = {
43 | events,
44 | ...nonEventProps
45 | };
46 | // if there are plotlines or bands, the chart needs to be redrawn before
47 | // they can be accessed
48 | if (axis.plotLinesAndBands && axis.plotLinesAndBands.length > 0) {
49 | axis.update(updateProps, true);
50 | } else {
51 | axis.update(updateProps, false);
52 | chart.needsRedraw();
53 | }
54 | }
55 | });
56 |
57 | if (!hasAxis) return null;
58 |
59 | return (
60 |
61 | {children}
62 |
63 | );
64 | };
65 |
66 | const getAxisConfig = props => {
67 | const { id = uuid, ...rest } = props;
68 |
69 | const axisId = typeof id === 'function' ? id() : id;
70 | const nonEventProps = getNonEventHandlerProps(rest);
71 | const events = getEventsConfig(rest);
72 |
73 | return {
74 | id: axisId,
75 | title: { text: null },
76 | events,
77 | ...nonEventProps
78 | };
79 | };
80 |
81 | const createAxis = (chart, props, dynamicAxis) => {
82 | const { id = uuid, isX } = props;
83 |
84 | // Create Highcharts Axis
85 | const opts = getAxisConfig(props);
86 | let axis;
87 | if (dynamicAxis) {
88 | axis = chart.addAxis(opts, isX, false);
89 | } else {
90 | // ZAxis cannot be added dynamically, Maps only have a single axes - update instead
91 | const axisId = typeof id === 'function' ? id() : id;
92 | axis = chart.get(axisId);
93 | axis.update.call(axis, opts, false);
94 | }
95 | return axis;
96 | };
97 |
98 | export default Axis;
99 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Axis/AxisTitle.js:
--------------------------------------------------------------------------------
1 | import { useEffect, memo } from 'react';
2 | import useAxis from '../UseAxis';
3 |
4 | const AxisTitle = memo(({ children: text, axisId, ...restProps }) => {
5 | const axis = useAxis(axisId);
6 |
7 | useEffect(() => {
8 | if (axis) {
9 | updateAxisTitle({ text, ...restProps }, axis);
10 | }
11 | });
12 |
13 | useEffect(() => {
14 | return () => {
15 | if (axis) {
16 | try {
17 | updateAxisTitle({ text: null }, axis);
18 | } catch {
19 | // ignore as axis might have been already unmounted
20 | }
21 | }
22 | };
23 | }, [axis]);
24 |
25 | return null;
26 | });
27 |
28 | const updateAxisTitle = (config, axis) => {
29 | axis.setTitle(config, true);
30 | };
31 |
32 | AxisTitle.displayName = 'AxisTitle';
33 |
34 | export default AxisTitle;
35 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Axis/createProvidedAxis.js:
--------------------------------------------------------------------------------
1 | const createProvidedAxis = axis => {
2 | if (!axis) return null;
3 |
4 | return {
5 | object: axis,
6 | id: axis.userOptions && axis.userOptions.id,
7 | type: axis.coll,
8 | update: axis.update.bind(axis),
9 | remove: axis.remove.bind(axis),
10 | addPlotBandOrLine: axis.addPlotBandOrLine.bind(axis),
11 | removePlotBandOrLine: axis.removePlotBandOrLine.bind(axis),
12 | getExtremes: axis.getExtremes.bind(axis),
13 | setExtremes: axis.setExtremes.bind(axis),
14 | setTitle: axis.setTitle.bind(axis)
15 | };
16 | };
17 |
18 | export default createProvidedAxis;
19 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Axis/index.js:
--------------------------------------------------------------------------------
1 | import Axis from './Axis';
2 | import AxisTitle from './AxisTitle';
3 | const ChartAxis = Axis;
4 | ChartAxis.Title = AxisTitle;
5 | export default ChartAxis;
6 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/AxisContext/index.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | const AxisContext = createContext();
4 | AxisContext.displayName = 'AxisContext';
5 |
6 | export default AxisContext;
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/BarSeries/BarSeries.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useEffect } from 'react';
3 | import Series from '../Series';
4 | import useChart from '../UseChart';
5 |
6 | const BarSeries = props => {
7 | const chart = useChart();
8 |
9 | useEffect(() => {
10 | chart.update({ chart: { inverted: true } });
11 | }, []);
12 |
13 | return ;
14 | };
15 |
16 | export default BarSeries;
17 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/BarSeries/index.js:
--------------------------------------------------------------------------------
1 | import BarSeries from './BarSeries';
2 | export default BarSeries;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/BaseChart/BaseChart.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useState, useEffect, useRef, useLayoutEffect } from 'react';
3 | import ChartContext from '../ChartContext';
4 | import usePrevious from '../UsePrevious';
5 | import createProvidedChart from './createProvidedChart';
6 |
7 | const noop = c => c;
8 |
9 | const BaseChart = ({
10 | children = null,
11 | callback = noop,
12 | className = '',
13 | containerProps = null,
14 | ...restProps
15 | }) => {
16 | const [rendered, setRendered] = useState(false);
17 | const domNodeRef = useRef(null);
18 | const chartRef = useRef(null);
19 | const providedChartRef = useRef(null);
20 |
21 | useLayoutEffect(() => {
22 | const myChart = initHighcharts(restProps, domNodeRef.current);
23 | chartRef.current = myChart;
24 | providedChartRef.current = createProvidedChart(
25 | myChart,
26 | restProps.chartType
27 | );
28 |
29 | callback(myChart);
30 | setRendered(true);
31 | }, []);
32 |
33 | useEffect(() => {
34 | const myChart = chartRef.current;
35 | return () => {
36 | if (myChart) {
37 | myChart.destroy.bind(myChart)();
38 | myChart.__destroyed = true;
39 | }
40 | };
41 | }, []);
42 |
43 | const prevProps = usePrevious(restProps);
44 | useEffect(() => {
45 | if (!rendered) return;
46 | const { plotOptions } = restProps;
47 | const myChart = chartRef.current;
48 |
49 | if (Object.is(prevProps.plotOptions, plotOptions) === false && myChart) {
50 | myChart.update({ plotOptions }, false);
51 | providedChartRef.current.needsRedraw();
52 | }
53 | });
54 |
55 | return (
56 |
57 | {rendered && (
58 |
59 | {children}
60 |
61 | )}
62 |
63 | );
64 | };
65 |
66 | const initHighcharts = (props, domNode) => {
67 | if (!domNode) {
68 | return;
69 | }
70 |
71 | const {
72 | chartCreationFunc,
73 | callback,
74 | chart,
75 | polar,
76 | gauge,
77 | styledMode = false,
78 | children,
79 | ...rest
80 | } = props;
81 |
82 | const opts = {
83 | chart: {
84 | styledMode,
85 | ...chart
86 | },
87 | title: {
88 | text: null
89 | },
90 | subtitle: {
91 | text: null
92 | },
93 | legend: {
94 | enabled: false
95 | },
96 | rangeSelector: {
97 | enabled: false
98 | },
99 | navigator: {
100 | enabled: false
101 | },
102 | scrollbar: {
103 | enabled: false
104 | },
105 | tooltip: {
106 | enabled: false
107 | },
108 | credits: {
109 | enabled: false
110 | },
111 | series: [],
112 | xAxis: [],
113 | yAxis: [],
114 | ...rest
115 | };
116 | const myChart = chartCreationFunc(domNode, opts);
117 |
118 | myChart.polar = polar;
119 | myChart.angular = gauge;
120 |
121 | return myChart;
122 | };
123 |
124 | export default BaseChart;
125 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/BaseChart/createProvidedChart.js:
--------------------------------------------------------------------------------
1 | import debounce from '../../utils/debounce-raf';
2 |
3 | const createProvidedChart = (chart, type) => ({
4 | object: chart,
5 | type,
6 | get: chart.get.bind(chart),
7 | setSize: chart.setSize.bind(chart),
8 | update: chart.update.bind(chart),
9 | addAxis: chart.addAxis.bind(chart),
10 | addColorAxis: chart.addColorAxis.bind(chart),
11 | addSeries: chart.addSeries.bind(chart),
12 | setTitle: chart.setTitle.bind(chart),
13 | setCaption: chart.setCaption.bind(chart),
14 | showLoading: chart.showLoading.bind(chart),
15 | hideLoading: chart.hideLoading.bind(chart),
16 | addCredits: chart.addCredits.bind(chart),
17 | addAnnotation: chart.addAnnotation ? chart.addAnnotation.bind(chart) : null,
18 | removeAnnotation: chart.removeAnnotation
19 | ? chart.removeAnnotation.bind(chart)
20 | : null,
21 | needsRedraw: debounce(() => {
22 | if (!chart.__destroyed) {
23 | try {
24 | chart.redraw.bind(chart)();
25 | } catch {
26 | // ignore
27 | }
28 | }
29 | })
30 | });
31 |
32 | export default createProvidedChart;
33 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/BaseChart/index.js:
--------------------------------------------------------------------------------
1 | import BaseChart from './BaseChart';
2 | export default BaseChart;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Caption/Caption.js:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import useChartUpdate from '../UseChartUpdate';
3 | const Caption = memo(props => {
4 | useChartUpdate(props, updateCaption, chart =>
5 | updateCaption(chart, { text: null })
6 | );
7 |
8 | return null;
9 | });
10 |
11 | const updateCaption = (chart, config) => {
12 | chart.setCaption(config);
13 | };
14 |
15 | Caption.displayName = 'Caption';
16 |
17 | export default Caption;
18 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Caption/index.js:
--------------------------------------------------------------------------------
1 | import Caption from './Caption';
2 | export default Caption;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Chart/Chart.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef, memo } from 'react';
2 | import { getNonEventHandlerProps } from '../../utils/events';
3 | import useModifiedProps from '../UseModifiedProps';
4 | import useChart from '../UseChart';
5 | import useManualEventHandlers from '../UseManualEventHandlers';
6 |
7 | const Chart = memo(({ type = 'line', width, height, ...restProps }) => {
8 | const chart = useChart();
9 | const mounted = useRef(false);
10 |
11 | const modifiedProps = useModifiedProps({ type, ...restProps });
12 |
13 | useEffect(() => {
14 | if (!(width === undefined && height === undefined)) {
15 | chart.setSize(width, height);
16 | }
17 | }, [width, height]);
18 |
19 | useEffect(() => {
20 | if (modifiedProps !== false && mounted.current) {
21 | const notEventProps = getNonEventHandlerProps(modifiedProps);
22 | if (Object.getOwnPropertyNames(notEventProps).length > 0) {
23 | updateChart(modifiedProps, chart, chart.needsRedraw);
24 | }
25 | }
26 | });
27 |
28 | useEffect(() => {
29 | const notEventProps = getNonEventHandlerProps({ type, ...restProps });
30 |
31 | updateChart(notEventProps, chart);
32 | mounted.current = true;
33 | }, []);
34 |
35 | useManualEventHandlers(restProps, chart.object);
36 |
37 | return null;
38 | });
39 |
40 | const updateChart = (config, chart) => {
41 | chart.update({ chart: config }, false);
42 | chart.needsRedraw();
43 | };
44 |
45 | Chart.displayName = 'Chart';
46 |
47 | export default Chart;
48 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Chart/index.js:
--------------------------------------------------------------------------------
1 | import Chart from './Chart';
2 | export default Chart;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/ChartContext/index.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | const ChartContext = createContext();
4 | ChartContext.displayName = 'ChartContext';
5 |
6 | export default ChartContext;
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/ColorAxis/ColorAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useEffect, useRef, useState } from 'react';
3 | import { v4 as uuid } from 'uuid';
4 | import { getNonEventHandlerProps, getEventsConfig } from '../../utils/events';
5 | import ColorAxisContext from '../ColorAxisContext';
6 | import useModifiedProps from '../UseModifiedProps';
7 | import useChart from '../UseChart';
8 | import createProvidedColorAxis from './createProvidedColorAxis';
9 |
10 | const ColorAxis = ({ children = null, ...restProps }) => {
11 | const chart = useChart();
12 | const colorAxisRef = useRef(null);
13 | const providedColorAxisRef = useRef(null);
14 | const [hasColorAxis, setHasColorAxis] = useState(false);
15 |
16 | useEffect(() => {
17 | const colorAxis = createColorAxis(chart, restProps);
18 | colorAxisRef.current = colorAxis;
19 | providedColorAxisRef.current = createProvidedColorAxis(
20 | colorAxisRef.current
21 | );
22 | setHasColorAxis(true);
23 | chart.needsRedraw();
24 |
25 | return () => {
26 | if (colorAxis && colorAxis.remove) {
27 | try {
28 | colorAxis.remove.bind(colorAxis)(false);
29 | } catch {
30 | // Axis may have already been removed, i.e. when Chart unmounted
31 | }
32 | chart.needsRedraw();
33 | }
34 | };
35 | }, []);
36 |
37 | const modifiedProps = useModifiedProps(restProps);
38 |
39 | useEffect(() => {
40 | if (colorAxisRef.current !== null && modifiedProps !== false) {
41 | const colorAxis = colorAxisRef.current;
42 | colorAxis.update(modifiedProps, false);
43 | chart.needsRedraw();
44 | }
45 | });
46 |
47 | if (!hasColorAxis) return null;
48 |
49 | return (
50 |
51 | {children}
52 |
53 | );
54 | };
55 |
56 | const getColorAxisConfig = props => {
57 | const { id = uuid, ...rest } = props;
58 |
59 | const colorAxisId = typeof id === 'function' ? id() : id;
60 | const nonEventProps = getNonEventHandlerProps(rest);
61 | const events = getEventsConfig(rest);
62 |
63 | return {
64 | id: colorAxisId,
65 | events,
66 | ...nonEventProps
67 | };
68 | };
69 |
70 | const createColorAxis = (chart, props) => {
71 | const opts = getColorAxisConfig(props);
72 | return chart.addColorAxis(opts, false);
73 | };
74 |
75 | export default ColorAxis;
76 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/ColorAxis/createProvidedColorAxis.js:
--------------------------------------------------------------------------------
1 | const createProvidedColorAxis = colorAxis => {
2 | if (!colorAxis) return null;
3 |
4 | return {
5 | object: colorAxis,
6 | id: colorAxis.userOptions && colorAxis.userOptions.id
7 | };
8 | };
9 |
10 | export default createProvidedColorAxis;
11 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/ColorAxis/index.js:
--------------------------------------------------------------------------------
1 | import ColorAxis from './ColorAxis';
2 |
3 | export default ColorAxis;
4 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/ColorAxisContext/index.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | const ColorAxisContext = createContext();
4 | ColorAxisContext.displayName = 'ColorAxisContext';
5 |
6 | export default ColorAxisContext;
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Credits/Credits.js:
--------------------------------------------------------------------------------
1 | import useChartUpdate from '../UseChartUpdate';
2 |
3 | const Credits = ({ enabled = true, ...restProps }) => {
4 | useChartUpdate({ enabled, ...restProps }, updateCredits, chart =>
5 | updateCredits(chart, { enabled: false })
6 | );
7 |
8 | return null;
9 | };
10 |
11 | const updateCredits = (chart, config) => {
12 | // Use default Highcharts value if text is not explicitly set
13 | if ('text' in config && !config.text) delete config.text;
14 | chart.addCredits(config, true);
15 | };
16 |
17 | export default Credits;
18 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Credits/index.js:
--------------------------------------------------------------------------------
1 | import Credits from './Credits';
2 | export default Credits;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Debug/Debug.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import useChart from '../UseChart';
3 |
4 | const Debug = ({ varName = 'chart' }) => {
5 | const chart = useChart();
6 |
7 | useEffect(() => {
8 | window[varName] = chart.object;
9 | // eslint-disable-next-line no-console
10 | console.log(
11 | `Chart instance available as global variable as window.${varName}`
12 | );
13 |
14 | return () => {
15 | window[varName] = undefined;
16 | };
17 | }, [varName]);
18 |
19 | return null;
20 | };
21 |
22 | export default Debug;
23 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Debug/index.js:
--------------------------------------------------------------------------------
1 | import Debug from './Debug';
2 | export default Debug;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Highcharts3dChart/Highcharts3dChart.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import HighchartsChart from '../HighchartsChart';
3 | import Options3d from '../Options3d';
4 |
5 | const CHART = {
6 | options3d: { enabled: true }
7 | };
8 | const ZAXIS = {
9 | id: 'zAxis'
10 | };
11 |
12 | const Highcharts3dChart = ({
13 | children,
14 | alpha,
15 | axisLabelPosition,
16 | beta,
17 | depth,
18 | fitToPlot,
19 | frame,
20 | viewDistance,
21 | ...rest
22 | }) => (
23 |
24 |
33 | {children}
34 |
35 | );
36 | Highcharts3dChart.propTypes = Options3d.propTypes;
37 |
38 | export default Highcharts3dChart;
39 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Highcharts3dChart/index.js:
--------------------------------------------------------------------------------
1 | import Highcharts3dChart from './Highcharts3dChart';
2 | export default Highcharts3dChart;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/HighchartsChart/HighchartsChart.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import BaseChart from '../BaseChart';
3 | import useHighcharts from '../UseHighcharts';
4 |
5 | const HighchartsChart = props => {
6 | const Highcharts = useHighcharts();
7 |
8 | return (
9 |
14 | );
15 | };
16 |
17 | export default HighchartsChart;
18 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/HighchartsChart/index.js:
--------------------------------------------------------------------------------
1 | import HighchartsChart from './HighchartsChart';
2 | export default HighchartsChart;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/HighchartsContext/index.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | const HighchartsContext = createContext();
4 | HighchartsContext.displayName = 'HighchartsContext';
5 | export default HighchartsContext;
6 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/HighchartsSparkline/HighchartsSparkline.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useMemo } from 'react';
3 | import HighchartsChart from '../HighchartsChart';
4 | import Chart from '../Chart';
5 | import XAxis from '../XAxis';
6 | import YAxis from '../YAxis';
7 |
8 | const defaultSparklinePlotOptions = {
9 | series: {
10 | animation: false,
11 | lineWidth: 1,
12 | shadow: false,
13 | states: {
14 | hover: {
15 | lineWidth: 1
16 | }
17 | },
18 | marker: {
19 | radius: 1,
20 | states: {
21 | hover: {
22 | radius: 2
23 | }
24 | }
25 | },
26 | fillOpacity: 0.25
27 | }
28 | };
29 |
30 | const EMPTY_ARRAY = [];
31 | const EMPTY_OBJECT = {};
32 | const ZERO_ARRAY = [0];
33 | const LABELS_DISABLED = { enabled: false };
34 | const DEFAULT_MARGIN = [2, 0, 2, 0];
35 |
36 | const HighchartsSparkline = ({
37 | height = 20,
38 | width = 120,
39 | margin = DEFAULT_MARGIN,
40 | style = EMPTY_OBJECT,
41 | series,
42 | children,
43 | plotOptions = defaultSparklinePlotOptions,
44 | ...rest
45 | }) => {
46 | const chartStyle = useMemo(
47 | () => ({ overflow: 'visible', ...style }),
48 | [style]
49 | );
50 |
51 | const hasSeriesProp = !!series;
52 | // If you want to use functionality like Tooltips, pass the data component on the `series` prop
53 | const Series = hasSeriesProp ? series : children;
54 |
55 | return (
56 |
57 |
67 |
68 |
74 |
75 |
82 | {Series}
83 |
84 |
85 | {hasSeriesProp && <>{children}>}
86 |
87 | );
88 | };
89 |
90 | export default HighchartsSparkline;
91 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/HighchartsSparkline/index.js:
--------------------------------------------------------------------------------
1 | import HighchartsSparkline from './HighchartsSparkline';
2 | export default HighchartsSparkline;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Legend/Legend.js:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import useChartUpdate from '../UseChartUpdate';
3 |
4 | const Legend = memo(({ children = null, enabled = true, ...restProps }) => {
5 | useChartUpdate(
6 | { enabled, ...restProps },
7 | updateLegend,
8 | chart => updateLegend(chart, { enabled: false }),
9 | false
10 | );
11 |
12 | return children;
13 | });
14 | const updateLegend = (chart, config) => {
15 | chart.update({ legend: config }, false);
16 | };
17 |
18 | Legend.displayName = 'Legend';
19 |
20 | export default Legend;
21 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Legend/LegendTitle.js:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import useChartUpdate from '../UseChartUpdate';
3 |
4 | const LegendTitle = memo(props => {
5 | useChartUpdate(props, updateLegendTitle, chart =>
6 | updateLegendTitle(chart, { text: null })
7 | );
8 |
9 | return null;
10 | });
11 |
12 | const updateLegendTitle = (chart, config) => {
13 | chart.update(
14 | {
15 | legend: {
16 | title: config
17 | }
18 | },
19 | false
20 | );
21 | };
22 |
23 | LegendTitle.displayName = 'LegendTitle';
24 |
25 | export default LegendTitle;
26 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Legend/index.js:
--------------------------------------------------------------------------------
1 | import Legend from './Legend';
2 | import LegendTitle from './LegendTitle';
3 | const ChartLegend = Legend;
4 | ChartLegend.Title = LegendTitle;
5 | export default ChartLegend;
6 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Loading/Loading.js:
--------------------------------------------------------------------------------
1 | import { useEffect, memo } from 'react';
2 | import useModifiedProps from '../UseModifiedProps';
3 | import useChart from '../UseChart';
4 |
5 | const Loading = memo(({ children, isLoading = true, ...restProps }) => {
6 | const chart = useChart();
7 | const modifiedProps = useModifiedProps(restProps);
8 |
9 | useEffect(() => {
10 | if (modifiedProps !== false) {
11 | updateLoading(modifiedProps, chart);
12 | }
13 | isLoading ? chart.showLoading(children) : chart.hideLoading();
14 | });
15 |
16 | useEffect(() => {
17 | return () => {
18 | try {
19 | chart.hideLoading();
20 | } catch {
21 | // ignore as chart might have been unmounted
22 | }
23 | };
24 | }, []);
25 |
26 | return null;
27 | });
28 |
29 | const updateLoading = (config, chart) => {
30 | chart.update({ loading: config }, true);
31 | };
32 |
33 | Loading.displayName = 'Loading';
34 | export default Loading;
35 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Loading/index.js:
--------------------------------------------------------------------------------
1 | import Loading from './Loading';
2 | export default Loading;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Options3d/Options3d.js:
--------------------------------------------------------------------------------
1 | import { useEffect, memo } from 'react';
2 | import { log3DModuleErrorMessage } from '../../utils/warnings';
3 | import useHighcharts from '../UseHighcharts';
4 | import useChart from '../UseChart';
5 |
6 | const DEFAULT_FRAME = {
7 | visible: 'default',
8 | size: 1,
9 | bottom: {},
10 | top: {},
11 | left: {},
12 | right: {},
13 | back: {},
14 | front: {}
15 | };
16 |
17 | const Options3d = memo(
18 | ({
19 | enabled = false,
20 | alpha = 0,
21 | beta = 0,
22 | depth = 100,
23 | fitToPlot = true,
24 | viewDistance = 25,
25 | axisLabelPosition = 'default',
26 | frame = DEFAULT_FRAME,
27 | ...restProps
28 | }) => {
29 | const props = {
30 | enabled,
31 | alpha,
32 | beta,
33 | depth,
34 | fitToPlot,
35 | viewDistance,
36 | axisLabelPosition,
37 | frame,
38 | ...restProps
39 | };
40 | const Highcharts = useHighcharts();
41 | const chart = useChart();
42 |
43 | if (process.env.NODE_ENV === 'development') {
44 | if (!Highcharts.ZAxis) log3DModuleErrorMessage();
45 | }
46 |
47 | useEffect(() => {
48 | update3dOptions(chart, props);
49 | });
50 |
51 | return null;
52 | }
53 | );
54 |
55 | const update3dOptions = (chart, props) => {
56 | const {
57 | alpha,
58 | axisLabelPosition,
59 | beta,
60 | depth,
61 | fitToPlot,
62 | frame,
63 | viewDistance
64 | } = props;
65 |
66 | const opts = {
67 | chart: {
68 | options3d: {
69 | enabled: true,
70 | alpha,
71 | axisLabelPosition,
72 | beta,
73 | depth,
74 | fitToPlot,
75 | frame,
76 | viewDistance
77 | }
78 | }
79 | };
80 | chart.update(opts, true);
81 | };
82 |
83 | Options3d.displayName = 'Options3d';
84 |
85 | export default Options3d;
86 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Options3d/index.js:
--------------------------------------------------------------------------------
1 | import Options3d from './Options3d';
2 | export default Options3d;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Pane/Pane.js:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import useChartUpdate from '../UseChartUpdate';
3 |
4 | const Pane = memo(({ children, ...restProps }) => {
5 | useChartUpdate(restProps, updatePane, chart => updatePane(chart, {}), false);
6 |
7 | return null;
8 | });
9 |
10 | const updatePane = (chart, config) => {
11 | chart.update({ pane: config }, false);
12 | };
13 | Pane.displayName = 'Pane';
14 |
15 | export default Pane;
16 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Pane/index.js:
--------------------------------------------------------------------------------
1 | import Pane from './Pane';
2 | export default Pane;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/PlotBandLine/PlotBand.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { memo } from 'react';
3 | import PlotBandLineContext from '../PlotBandLineContext';
4 | import usePlotBandLineLifecycle from './UsePlotBandLineLifecycle';
5 |
6 | const PlotBand = memo(props => {
7 | const plotband = usePlotBandLineLifecycle(props, 'plotBands');
8 |
9 | const { children } = props;
10 |
11 | if (!children && !plotband) return null;
12 |
13 | return (
14 |
15 | {children}
16 |
17 | );
18 | });
19 |
20 | PlotBand.displayName = 'PlotBand';
21 | export default PlotBand;
22 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/PlotBandLine/PlotBandLineLabel.js:
--------------------------------------------------------------------------------
1 | import { useEffect, memo } from 'react';
2 | import usePlotBandLine from '../UsePlotBandLine';
3 |
4 | const PlotBandLineLabel = memo(props => {
5 | const providedPlotbandline = usePlotBandLine();
6 |
7 | useEffect(() => {
8 | if (!providedPlotbandline) return;
9 | const { children: text, id, ...rest } = props;
10 | updatePlotBandLineLabel(providedPlotbandline.object, {
11 | text,
12 | ...rest
13 | });
14 | });
15 |
16 | useEffect(() => {
17 | return () => {
18 | if (!providedPlotbandline) return;
19 | try {
20 | updatePlotBandLineLabel(providedPlotbandline.object, {
21 | text: null
22 | });
23 | } catch {
24 | // ignore as axis might have been unmounted
25 | }
26 | };
27 | }, []);
28 |
29 | return null;
30 | });
31 |
32 | const updatePlotBandLineLabel = (plotbandline, config) => {
33 | if (plotbandline) {
34 | plotbandline.options.label = getLabelProps(config);
35 | plotbandline.render();
36 | }
37 | };
38 |
39 | const getLabelProps = props => {
40 | const {
41 | text,
42 | formatter,
43 | align,
44 | rotation,
45 | style,
46 | textAlign,
47 | useHTML,
48 | verticalAlign,
49 | x,
50 | y
51 | } = props;
52 |
53 | return {
54 | text,
55 | formatter,
56 | align,
57 | rotation,
58 | style,
59 | textAlign,
60 | useHTML,
61 | verticalAlign,
62 | x,
63 | y
64 | };
65 | };
66 |
67 | PlotBandLineLabel.displayName = 'PlotBandLineLabel';
68 |
69 | export default PlotBandLineLabel;
70 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/PlotBandLine/PlotLine.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { memo } from 'react';
3 | import PlotBandLineContext from '../PlotBandLineContext';
4 | import usePlotBandLineLifecycle from './UsePlotBandLineLifecycle';
5 |
6 | const PlotLine = memo(props => {
7 | const plotline = usePlotBandLineLifecycle(props, 'plotLines');
8 |
9 | const { children } = props;
10 |
11 | if (!children && !plotline) return null;
12 |
13 | return (
14 |
15 | {children}
16 |
17 | );
18 | });
19 |
20 | PlotLine.displayName = 'PlotLine';
21 | export default PlotLine;
22 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/PlotBandLine/UsePlotBandLineLifecycle.js:
--------------------------------------------------------------------------------
1 | import { useRef, useEffect, useState } from 'react';
2 | import { v4 as uuid } from 'uuid';
3 | import useModifiedProps from '../UseModifiedProps';
4 | import useAxis from '../UseAxis';
5 |
6 | export default function usePlotBandLineLifecycle(props, plotType) {
7 | const { id = uuid, axisId, children, ...rest } = props;
8 |
9 | const axis = useAxis(axisId);
10 | const idRef = useRef();
11 | const [plotbandline, setPlotbandline] = useState(null);
12 | const modifiedProps = useModifiedProps(rest);
13 |
14 | useEffect(() => {
15 | if (!axis) return;
16 | if (!plotbandline || modifiedProps !== false) {
17 | if (!plotbandline) {
18 | idRef.current = typeof id === 'function' ? id() : id;
19 | }
20 | const myId = idRef.current;
21 | const opts = {
22 | id: myId,
23 | ...rest
24 | };
25 |
26 | if (plotbandline) axis.removePlotBandOrLine(idRef.current);
27 | axis.addPlotBandOrLine(opts, plotType);
28 | setPlotbandline({
29 | id: myId,
30 | get object() {
31 | /* when parent axis is updated, the plotlines and plotbands are recreated
32 | therefore the object can't be cached here
33 | */
34 | if (axis && axis.object && axis.object.plotLinesAndBands) {
35 | return axis.object.plotLinesAndBands.find(plb => plb.id === myId);
36 | }
37 | return null;
38 | }
39 | });
40 | }
41 | });
42 |
43 | useEffect(() => {
44 | return () => {
45 | try {
46 | axis.removePlotBandOrLine(idRef.current);
47 | } catch {
48 | // ignore as axis might have been already unmounted
49 | }
50 | };
51 | }, []);
52 |
53 | return plotbandline;
54 | }
55 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/PlotBandLine/index.js:
--------------------------------------------------------------------------------
1 | import PlotBand from './PlotBand';
2 | import PlotLine from './PlotLine';
3 | import PlotBandLineLabel from './PlotBandLineLabel';
4 |
5 | const ChartPlotBand = PlotBand;
6 | ChartPlotBand.Label = PlotBandLineLabel;
7 | const ChartPlotLine = PlotLine;
8 | ChartPlotLine.Label = PlotBandLineLabel;
9 |
10 | export { ChartPlotLine as PlotLine };
11 | export { ChartPlotBand as PlotBand };
12 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/PlotBandLineContext/index.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | const PlotBandLineContext = createContext();
4 |
5 | PlotBandLineContext.displayName = 'PlotBandLineContext';
6 |
7 | export default PlotBandLineContext;
8 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Series/createProvidedSeries.js:
--------------------------------------------------------------------------------
1 | export default function createProvidedSeries(series) {
2 | if (!series) return null;
3 |
4 | return {
5 | object: series,
6 | id: series.userOptions && series.userOptions.id,
7 | type: series.type,
8 | update: series.update.bind(series),
9 | remove: series.remove.bind(series),
10 | setData: series.setData.bind(series),
11 | setVisible: series.setVisible.bind(series)
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Series/index.js:
--------------------------------------------------------------------------------
1 | import Series from './Series';
2 | export default Series;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/SeriesContext/index.js:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react';
2 |
3 | const SeriesContext = createContext();
4 | SeriesContext.displayName = 'SeriesContext';
5 |
6 | export default SeriesContext;
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Subtitle/Subtitle.js:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import useChartUpdate from '../UseChartUpdate';
3 |
4 | const Subtitle = memo(props => {
5 | useChartUpdate(props, updateSubtitle, chart =>
6 | updateSubtitle(chart, { text: null })
7 | );
8 |
9 | return null;
10 | });
11 |
12 | const updateSubtitle = (chart, config) => {
13 | chart.setTitle(undefined, config, false);
14 | };
15 |
16 | Subtitle.displayName = 'Subtitle';
17 |
18 | export default Subtitle;
19 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Subtitle/index.js:
--------------------------------------------------------------------------------
1 | import Subtitle from './Subtitle';
2 | export default Subtitle;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Title/Title.js:
--------------------------------------------------------------------------------
1 | import { memo } from 'react';
2 | import useChartUpdate from '../UseChartUpdate';
3 |
4 | const Title = memo(props => {
5 | useChartUpdate(props, updateTitle, chart =>
6 | updateTitle(chart, { text: null })
7 | );
8 |
9 | return null;
10 | });
11 |
12 | const updateTitle = (chart, config) => {
13 | chart.setTitle(config, null, false);
14 | };
15 |
16 | Title.displayName = 'Title';
17 |
18 | export default Title;
19 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Title/index.js:
--------------------------------------------------------------------------------
1 | import Title from './Title';
2 | export default Title;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Tooltip/Tooltip.js:
--------------------------------------------------------------------------------
1 | import { useEffect, memo } from 'react';
2 | import useChart from '../UseChart';
3 | import useHighcharts from '../UseHighcharts';
4 | import useModifiedProps from '../UseModifiedProps';
5 |
6 | const Tooltip = memo(props => {
7 | // eslint-disable-next-line no-unused-vars
8 | const { children = null, ...restProps } = props;
9 | const chart = useChart();
10 | const Highcharts = useHighcharts();
11 |
12 | restProps.enabled = props.enabled ?? true;
13 |
14 | useEffect(() => {
15 | updateTooltip(chart, {
16 | ...(Highcharts.defaultOptions && Highcharts.defaultOptions.tooltip),
17 | ...restProps
18 | });
19 |
20 | return () => {
21 | try {
22 | updateTooltip(chart, { enabled: false });
23 | } catch {
24 | // ignore as chart might have been already unmounted
25 | }
26 | };
27 | }, []);
28 |
29 | const modifiedProps = useModifiedProps(restProps);
30 | useEffect(() => {
31 | if (modifiedProps !== false) {
32 | updateTooltip(chart, modifiedProps);
33 | }
34 | });
35 |
36 | return null;
37 | });
38 |
39 | const updateTooltip = (chart, config) => {
40 | chart.update({
41 | tooltip: config
42 | });
43 | };
44 |
45 | Tooltip.displayName = 'Tooltip';
46 |
47 | export default Tooltip;
48 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/Tooltip/index.js:
--------------------------------------------------------------------------------
1 | import Tooltip from './Tooltip';
2 | export default Tooltip;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseAxis/index.js:
--------------------------------------------------------------------------------
1 | import { useContext, useState, useEffect, useDebugValue } from 'react';
2 | import AxisContext from '../AxisContext';
3 | import useChart from '../UseChart';
4 | import createProvidedAxis from '../Axis/createProvidedAxis';
5 |
6 | export default function useAxis(axisId) {
7 | const chart = useChart();
8 | const contextAxis = useContext(AxisContext);
9 |
10 | const createStateAxis = () => {
11 | if (contextAxis) return contextAxis;
12 |
13 | if (axisId) {
14 | const axis = chart.get(axisId);
15 | return createProvidedAxis(axis);
16 | }
17 | return null;
18 | };
19 |
20 | const [providedAxis, setProvidedAxis] = useState(createStateAxis);
21 | useEffect(() => {
22 | if (providedAxis) return; // we already had axis
23 | // axis should now be created
24 | setProvidedAxis(createStateAxis());
25 | }, []);
26 | useDebugValue(providedAxis ? providedAxis.id : null);
27 |
28 | return providedAxis;
29 | }
30 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseChart/index.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import ChartContext from '../ChartContext';
3 |
4 | export default function useChart() {
5 | return useContext(ChartContext);
6 | }
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseChartUpdate/index.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import useChart from '../UseChart';
3 | import useModifiedProps from '../UseModifiedProps';
4 |
5 | const noop = c => c;
6 |
7 | const useChartUpdate = (
8 | props,
9 | updateFn = noop,
10 | destroyFn = noop,
11 | childrenIsText = true
12 | ) => {
13 | const chart = useChart();
14 | const modifiedProps = useModifiedProps(props, childrenIsText);
15 |
16 | useEffect(() => {
17 | if (modifiedProps !== false) {
18 | updateFn(chart, modifiedProps);
19 | chart.needsRedraw();
20 | }
21 | });
22 |
23 | useEffect(() => {
24 | return () => {
25 | try {
26 | destroyFn(chart);
27 | } catch {
28 | // ignore as chart might have been already unmounted
29 | }
30 | chart.needsRedraw();
31 | };
32 | }, []);
33 | };
34 |
35 | export default useChartUpdate;
36 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseColorAxis/index.js:
--------------------------------------------------------------------------------
1 | import { useContext, useState, useEffect, useDebugValue } from 'react';
2 | import ColorAxisContext from '../ColorAxisContext';
3 | import useChart from '../UseChart';
4 | import createProvidedColorAxis from '../ColorAxis/createProvidedColorAxis';
5 |
6 | export default function useColorAxis(colorAxisId) {
7 | const chart = useChart();
8 | const contextColorAxis = useContext(ColorAxisContext);
9 |
10 | const createStateColorAxis = () => {
11 | if (contextColorAxis) return contextColorAxis;
12 |
13 | if (colorAxisId) {
14 | const colorAxis = chart.get(colorAxisId);
15 | return createProvidedColorAxis(colorAxis);
16 | }
17 | return null;
18 | };
19 |
20 | const [providedColorAxis, setProvidedColorAxis] =
21 | useState(createStateColorAxis);
22 |
23 | useEffect(() => {
24 | if (providedColorAxis) return; // we already had axis
25 | // axis should now be created
26 | setProvidedColorAxis(createStateColorAxis());
27 | }, []);
28 |
29 | useDebugValue(providedColorAxis ? providedColorAxis.id : null);
30 |
31 | return providedColorAxis;
32 | }
33 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseHighcharts/index.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import HighchartsContext from '../HighchartsContext';
3 |
4 | export default function useHighcharts() {
5 | return useContext(HighchartsContext);
6 | }
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseManualEventHandlers/index.js:
--------------------------------------------------------------------------------
1 | import useHighcharts from '../UseHighcharts';
2 | import usePrevious from '../UsePrevious';
3 | import { getEventsConfig } from '../../utils/events';
4 | import getModifiedProps from '../../utils/getModifiedProps';
5 |
6 | const useManualEventHandlers = function (props, target) {
7 | const Highcharts = useHighcharts();
8 | const eventHandlers = getEventsConfig(props);
9 | const previousEventHandlers = usePrevious(eventHandlers);
10 |
11 | const modifiedEvenHandlers = getModifiedProps(
12 | previousEventHandlers,
13 | eventHandlers
14 | );
15 |
16 | if (modifiedEvenHandlers !== false) {
17 | Object.keys(modifiedEvenHandlers).forEach(eventName => {
18 | if (previousEventHandlers) {
19 | const oldHandler = previousEventHandlers[eventName];
20 | if (oldHandler) {
21 | Highcharts.removeEvent(target, eventName, oldHandler);
22 | }
23 | }
24 | const newHandler = modifiedEvenHandlers[eventName];
25 | if (newHandler) {
26 | Highcharts.addEvent(target, eventName, newHandler);
27 | }
28 | });
29 | }
30 | };
31 |
32 | export default useManualEventHandlers;
33 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseModifiedProps/index.js:
--------------------------------------------------------------------------------
1 | import { useRef, useEffect, useDebugValue } from 'react';
2 | import getModifiedProps from '../../utils/getModifiedProps';
3 |
4 | export default function useModifiedProps(props, childrenIsText = false) {
5 | const ref = useRef();
6 | useEffect(() => {
7 | ref.current = props;
8 | });
9 | const modifiedProps = getModifiedProps(ref.current, props, childrenIsText);
10 |
11 | useDebugValue(modifiedProps ? 'Modified' : 'Not modified');
12 |
13 | return modifiedProps;
14 | }
15 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UsePlotBandLine/index.js:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react';
2 | import PlotLineContext from '../PlotBandLineContext';
3 |
4 | export default function usePlotBandLine() {
5 | return useContext(PlotLineContext);
6 | }
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UsePrevious/index.js:
--------------------------------------------------------------------------------
1 | import { useRef, useEffect } from 'react';
2 |
3 | export default function usePrevious(value) {
4 | const ref = useRef();
5 | useEffect(() => {
6 | ref.current = value;
7 | });
8 | return ref.current;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/UseSeries/index.js:
--------------------------------------------------------------------------------
1 | import { useContext, useState, useEffect, useDebugValue } from 'react';
2 | import SeriesContext from '../SeriesContext';
3 | import useChart from '../UseChart';
4 | import createProvidedSeries from '../Series/createProvidedSeries';
5 |
6 | export default function useSeries(seriesId) {
7 | const contextSeries = useContext(SeriesContext);
8 | const chart = useChart();
9 |
10 | const createStateSeries = () => {
11 | if (contextSeries) return contextSeries;
12 |
13 | if (seriesId) {
14 | const mySeries = chart.get(seriesId);
15 | return createProvidedSeries(mySeries);
16 | }
17 | return null;
18 | };
19 |
20 | const [providedSeries, setProvidedSeries] = useState(createStateSeries);
21 | useEffect(() => {
22 | if (providedSeries) return; // we already had series
23 | // series should now be created
24 | setProvidedSeries(createStateSeries());
25 | }, []);
26 | useDebugValue(providedSeries ? providedSeries.id : null);
27 |
28 | return providedSeries;
29 | }
30 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/WithHighcharts/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import HighchartsContext from '../HighchartsContext';
3 |
4 | // This is a HOC function.
5 | // It takes a component...
6 | export default function withHighcharts(Component, Highcharts) {
7 | // ...and returns another component...
8 | return function HighchartsWrappedComponent(props) {
9 | // ... and renders the wrapped component with the context theme!
10 | // Notice that we pass through any additional props as well
11 | return (
12 |
13 |
14 |
15 | );
16 | };
17 | }
18 |
19 | export const HighchartsProvider = ({ Highcharts, children }) => (
20 |
21 | {children}
22 |
23 | );
24 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/WithSeriesType/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Series from '../Series';
3 |
4 | // This HOC returns Series component with injected type
5 | export default function withSeriesType(seriesType, additionalProps = {}) {
6 | const SeriesComponent = props => (
7 |
8 | );
9 |
10 | SeriesComponent.displayName = `${seriesType}Series`;
11 |
12 | return SeriesComponent;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/XAxis/XAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Axis from '../Axis';
3 | import useChart from '../UseChart';
4 |
5 | const XAxis = ({ id, ...rest }) => {
6 | const chart = useChart();
7 |
8 | const isStockChart = chart.type === 'stockChart';
9 | const type = isStockChart ? 'datetime' : 'linear';
10 | const axisId = isStockChart ? 'xAxis' : id;
11 |
12 | return ;
13 | };
14 |
15 | export default XAxis;
16 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/XAxis/index.js:
--------------------------------------------------------------------------------
1 | import XAxis from './XAxis';
2 | import Axis from '../Axis';
3 | const ChartXAxis = XAxis;
4 | ChartXAxis.Title = Axis.Title;
5 | export default ChartXAxis;
6 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/YAxis/YAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Axis from '../Axis';
3 |
4 | const YAxis = ({ type = 'linear', ...restProps }) => (
5 |
6 | );
7 |
8 | YAxis.displayName = 'YAxis';
9 |
10 | YAxis.Title = Axis.Title;
11 | export default YAxis;
12 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/YAxis/index.js:
--------------------------------------------------------------------------------
1 | import YAxis from './YAxis';
2 | export default YAxis;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/ZAxis/ZAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Axis from '../Axis';
3 |
4 | const ZAxis = ({ type = 'linear', ...restProps }) => (
5 |
6 | );
7 |
8 | ZAxis.displayName = 'ZAxis';
9 | ZAxis.Title = Axis.Title;
10 | export default ZAxis;
11 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/components/ZAxis/index.js:
--------------------------------------------------------------------------------
1 | import ZAxis from './ZAxis';
2 | export default ZAxis;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/utils/debounce-raf.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2019, Hyperdivision ApS
3 |
4 | Permission to use, copy, modify, and/or distribute this software for any
5 | purpose with or without fee is hereby granted, provided that the above
6 | copyright notice and this permission notice appear in all copies.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 | */
16 |
17 | export default function (fn) {
18 | const cancelAnimationFrame = window.cancelAnimationFrame;
19 | const requestAnimationFrame = window.requestAnimationFrame;
20 |
21 | var queued;
22 | return function (...args) {
23 | if (queued) cancelAnimationFrame(queued);
24 |
25 | queued = requestAnimationFrame(fn.bind(fn, ...args));
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/utils/events.js:
--------------------------------------------------------------------------------
1 | import pickBy from './pickBy';
2 |
3 | export const getEventHandlerProps = props => {
4 | return pickBy(props, _isEventKey);
5 | };
6 |
7 | export const getNonEventHandlerProps = props => {
8 | return pickBy(props, (key, value) => !_isEventKey(key, value));
9 | };
10 |
11 | export const getEventsConfig = props => {
12 | const eventProps = getEventHandlerProps(props);
13 | const eventsConfig = {};
14 |
15 | Object.keys(eventProps).forEach(eventName => {
16 | const configName = eventName.slice(2)[0].toLowerCase() + eventName.slice(3);
17 | eventsConfig[configName] = eventProps[eventName];
18 | });
19 |
20 | return eventsConfig;
21 | };
22 |
23 | const _isEventKey = (key, value) =>
24 | key.indexOf('on') === 0 && key.length > 2 && typeof value === 'function';
25 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/utils/getModifiedProps.js:
--------------------------------------------------------------------------------
1 | import pickBy from './pickBy';
2 |
3 | export default function getModifiedProps(
4 | prevProps,
5 | currProps,
6 | childrenIsText = false
7 | ) {
8 | let { children, ...rest } = currProps;
9 |
10 | const modifiedProps = pickBy(rest, (propName, value) => {
11 | if (!prevProps) return true;
12 |
13 | return Object.is(value, prevProps[propName]) === false;
14 | });
15 |
16 | if (
17 | childrenIsText &&
18 | (!prevProps || Object.is(prevProps.children, children) === false)
19 | ) {
20 | modifiedProps.text = children;
21 | }
22 |
23 | if (Object.keys(modifiedProps).length > 0) {
24 | return modifiedProps;
25 | }
26 |
27 | return false;
28 | }
29 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/src/utils/pickBy.js:
--------------------------------------------------------------------------------
1 | export default function (obj, filterFn) {
2 | let retProps = {};
3 | if (obj) {
4 | Object.keys(obj)
5 | .filter(key => filterFn(key, obj[key]))
6 | .forEach(key => {
7 | retProps[key] = obj[key];
8 | });
9 | }
10 | return retProps;
11 | }
12 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | "jest": true
5 | },
6 | "rules": {
7 | "no-unused-vars": ["warn"],
8 | "react-perf/jsx-no-new-function-as-prop": "off",
9 | "react-perf/jsx-no-new-object-as-prop": "off",
10 | "react-perf/jsx-no-new-array-as-prop": "off",
11 | "react/display-name": "off"
12 | },
13 | "globals": {
14 | "mount": true,
15 | "shallow": true,
16 | "render": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/ContextSpy.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import {
3 | useAxis,
4 | useChart,
5 | useHighcharts,
6 | useSeries,
7 | usePlotBandLine
8 | } from '../src';
9 |
10 | const ContextSpy = ({
11 | axisId,
12 | axisRef,
13 | chartRef,
14 | highchartsRef,
15 | seriesRef,
16 | plotBandLineRef
17 | }) => {
18 | const axis = useAxis(axisId);
19 | const chart = useChart();
20 | const Highcharts = useHighcharts();
21 | const series = useSeries();
22 | const plotbandline = usePlotBandLine();
23 |
24 | useEffect(() => {
25 | if (highchartsRef) {
26 | highchartsRef.current = Highcharts;
27 | }
28 |
29 | return () => {
30 | if (highchartsRef) {
31 | highchartsRef.current = null;
32 | }
33 | };
34 | }, [Highcharts]);
35 |
36 | useEffect(() => {
37 | if (chartRef) {
38 | chartRef.current = chart;
39 | }
40 |
41 | return () => {
42 | if (chartRef) {
43 | chartRef.current = null;
44 | }
45 | };
46 | }, [chart]);
47 |
48 | useEffect(() => {
49 | if (axisRef) {
50 | axisRef.current = axis;
51 | axisRef.addPlotBandOrLineSpy = jest.spyOn(axis, 'addPlotBandOrLine');
52 | axisRef.removePlotBandOrLineSpy = jest.spyOn(
53 | axis,
54 | 'removePlotBandOrLine'
55 | );
56 | }
57 |
58 | return () => {
59 | if (axisRef) {
60 | axisRef.addPlotBandOrLineSpy.mockRestore();
61 | axisRef.removePlotBandOrLineSpy.mockRestore();
62 | axisRef.current = null;
63 | }
64 | };
65 | }, [axis]);
66 |
67 | useEffect(() => {
68 | if (seriesRef) {
69 | seriesRef.current = series;
70 | }
71 |
72 | return () => {
73 | if (seriesRef) {
74 | seriesRef.current = null;
75 | }
76 | };
77 | }, [series]);
78 |
79 | useEffect(() => {
80 | if (plotBandLineRef) {
81 | plotBandLineRef.current = plotbandline;
82 | }
83 |
84 | return () => {
85 | if (plotBandLineRef) {
86 | plotBandLineRef.current = null;
87 | }
88 | };
89 | }, [plotbandline]);
90 |
91 | return null;
92 | };
93 |
94 | export default ContextSpy;
95 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Axis/Axis.integration.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Highcharts from 'highcharts';
3 | import addAccessibility from 'highcharts/modules/accessibility';
4 |
5 | import { render } from '@testing-library/react';
6 |
7 | import { HighchartsChart, HighchartsProvider } from '../../../src';
8 | import Axis from '../../../src/components/Axis';
9 | import ContextSpy from '../../ContextSpy';
10 |
11 | addAccessibility(Highcharts);
12 |
13 | describe(' integration', () => {
14 | describe('when rendered to document', () => {
15 | it('fires afterInit event', done => {
16 | const onAfterInit = () => {
17 | expect(true).toBe(true);
18 | done();
19 | };
20 | const Component = () => {
21 | return (
22 |
23 |
24 |
25 |
26 |
27 | );
28 | };
29 |
30 | render();
31 | });
32 | });
33 | describe('when updated', () => {
34 | it('updates eventhandlers', () => {
35 | const axisRef = {};
36 |
37 | const Component = ({ axisProps }) => {
38 | return (
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | );
47 | };
48 |
49 | const { rerender } = render();
50 |
51 | const onSetExtremes = jest.fn();
52 |
53 | rerender();
54 |
55 | const onSetExtremes2 = jest.fn();
56 | axisRef.current.setExtremes(10, 20);
57 | expect(onSetExtremes).toHaveBeenCalledTimes(1);
58 | onSetExtremes.mockClear();
59 |
60 | rerender();
61 |
62 | axisRef.current.setExtremes(100, 200);
63 | expect(onSetExtremes).not.toHaveBeenCalled();
64 |
65 | expect(onSetExtremes2).toHaveBeenCalledTimes(1);
66 | });
67 | });
68 | });
69 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Axis/AxisTitle.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedAxis } from '../../test-utils';
5 | import AxisTitle from '../../../src/components/Axis/AxisTitle';
6 | import * as useAxis from '../../../src/components/UseAxis';
7 |
8 | describe('', () => {
9 | let testContext;
10 | let useAxisSpy;
11 |
12 | beforeEach(() => {
13 | testContext = {};
14 |
15 | const { axisStubs, providedAxis } = createMockProvidedAxis({
16 | id: 'myAxis',
17 | type: 'yAxis'
18 | });
19 | testContext.axisStubs = axisStubs;
20 | useAxisSpy = jest
21 | .spyOn(useAxis, 'default')
22 | .mockImplementation(() => providedAxis);
23 | });
24 |
25 | afterEach(() => {
26 | useAxisSpy.mockRestore();
27 | });
28 |
29 | describe('when mounted', () => {
30 | it('sets the correct axis title', () => {
31 | render(My Axis Title);
32 | expect(testContext.axisStubs.setTitle).toHaveBeenCalledWith(
33 | {
34 | text: 'My Axis Title'
35 | },
36 | expect.any(Boolean)
37 | );
38 | });
39 |
40 | it('should pass additional props too', () => {
41 | render(My Axis Title);
42 | expect(testContext.axisStubs.setTitle).toHaveBeenCalledWith(
43 | {
44 | text: 'My Axis Title',
45 | align: 'high'
46 | },
47 | expect.any(Boolean)
48 | );
49 | });
50 | });
51 |
52 | describe('update', () => {
53 | it('should setTitle the correct axis title if the component props change', () => {
54 | const wrapper = render(My Axis Title);
55 | testContext.axisStubs.setTitle.mockClear();
56 |
57 | wrapper.rerender(
58 |
59 | New Title
60 |
61 | );
62 |
63 | expect(testContext.axisStubs.setTitle).toHaveBeenCalledWith(
64 | {
65 | text: 'New Title',
66 | dimension: 'x'
67 | },
68 | expect.any(Boolean)
69 | );
70 | });
71 | });
72 |
73 | describe('when unmounted', () => {
74 | it('removes the correct axis title (if the axis still exists)', () => {
75 | const wrapper = render(My Axis Title);
76 | wrapper.unmount();
77 | expect(testContext.axisStubs.setTitle).toHaveBeenCalledWith(
78 | {
79 | text: null
80 | },
81 | expect.any(Boolean)
82 | );
83 | });
84 | });
85 | });
86 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/BarSeries/BarSeries.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import {
5 | Highcharts,
6 | createMockProvidedChart,
7 | createMockProvidedAxis
8 | } from '../../test-utils';
9 | import BarSeries from '../../../src/components/BarSeries/BarSeries';
10 | import ChartContext from '../../../src/components/ChartContext';
11 | import AxisContext from '../../../src/components/AxisContext';
12 | import HighchartsContext from '../../../src/components/HighchartsContext';
13 |
14 | describe('', () => {
15 | let testContext;
16 | let ProvidedBarSeries;
17 | beforeEach(() => {
18 | testContext = {};
19 |
20 | const { chartStubs } = createMockProvidedChart();
21 | const { providedAxis } = createMockProvidedAxis({
22 | id: 'myAxis',
23 | type: 'yAxis'
24 | });
25 | testContext.chartStubs = chartStubs;
26 | testContext.providedAxis = providedAxis;
27 |
28 | const highchartsValue = () => Highcharts;
29 |
30 | ProvidedBarSeries = props => (
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | );
39 | });
40 |
41 | it('adds a series with type="bar" />', () => {
42 | render();
43 | expect(testContext.chartStubs.addSeries).toHaveBeenCalledWith(
44 | expect.objectContaining({ type: 'bar' }),
45 | false
46 | );
47 | });
48 |
49 | it('passes other props through to series', () => {
50 | render();
51 | expect(testContext.chartStubs.addSeries).toHaveBeenCalledWith(
52 | expect.objectContaining({ data: [1, 2, 3, 4] }),
53 | false
54 | );
55 | });
56 |
57 | it('inverts the chart on mount', () => {
58 | render();
59 | expect(testContext.chartStubs.update).toHaveBeenCalledWith({
60 | chart: {
61 | inverted: true
62 | }
63 | });
64 | });
65 | });
66 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Caption/Caption.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 | import Caption from '../../../src/components/Caption/Caption';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | describe('', () => {
9 | let testContext;
10 | let ProvidedCaption;
11 |
12 | beforeEach(() => {
13 | testContext = {};
14 | const { chartStubs, needsRedraw } = createMockProvidedChart();
15 | testContext.chartStubs = chartStubs;
16 | testContext.needsRedraw = needsRedraw;
17 |
18 | ProvidedCaption = props => (
19 |
20 |
21 |
22 | );
23 | });
24 |
25 | describe('when mounted', () => {
26 | it('adds a caption using the Highcharts setCaption method', () => {
27 | render(My Caption);
28 | expect(testContext.chartStubs.setCaption).toHaveBeenCalledWith({
29 | text: 'My Caption'
30 | });
31 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
32 | });
33 |
34 | it('should pass additional props through to Highcharts setTitle method', () => {
35 | render(My Other Caption);
36 | expect(testContext.chartStubs.setCaption).toHaveBeenCalledWith({
37 | text: 'My Other Caption',
38 | align: 'right'
39 | });
40 | });
41 | });
42 |
43 | describe('update', () => {
44 | it('should use the setCaption method when the data changes', () => {
45 | const wrapper = render(My Caption);
46 | wrapper.rerender(
47 |
48 | My New Caption
49 |
50 | );
51 |
52 | expect(testContext.chartStubs.setCaption).toHaveBeenCalledWith({
53 | x: 10,
54 | y: 20,
55 | text: 'My New Caption'
56 | });
57 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(2);
58 | });
59 | });
60 |
61 | describe('when unmounted', () => {
62 | it('removes the caption by setting the text to null', () => {
63 | const wrapper = render(My Caption);
64 | wrapper.unmount();
65 | expect(testContext.chartStubs.setCaption).toHaveBeenCalledWith({
66 | text: null
67 | });
68 | expect(testContext.chartStubs.setCaption).toHaveBeenCalledTimes(2);
69 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(2);
70 | });
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Credits/Credits.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 | import Credits from '../../../src/components/Credits/Credits';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | describe('', () => {
9 | let testContext;
10 | let ProvidedCredits;
11 |
12 | beforeEach(() => {
13 | testContext = {};
14 | const { chartStubs } = createMockProvidedChart();
15 | testContext.chartStubs = chartStubs;
16 |
17 | ProvidedCredits = props => (
18 |
19 |
20 |
21 | );
22 | });
23 |
24 | describe('when mounted', () => {
25 | it('add credits using the Highcharts addCredits method', () => {
26 | render(github.com);
27 | expect(testContext.chartStubs.addCredits).toHaveBeenCalledWith(
28 | {
29 | enabled: true,
30 | text: 'github.com'
31 | },
32 | true
33 | );
34 | expect(testContext.chartStubs.addCredits).toHaveBeenCalledTimes(1);
35 | });
36 |
37 | it('addCreditss the credits with the passed props', () => {
38 | render(
39 |
40 | github.com
41 |
42 | );
43 | expect(testContext.chartStubs.addCredits).toHaveBeenCalledWith(
44 | {
45 | enabled: true,
46 | href: 'https://www.github.com',
47 | text: 'github.com'
48 | },
49 | true
50 | );
51 | });
52 | });
53 |
54 | describe('addCredits', () => {
55 | it('should use the addCredits method when props change', () => {
56 | const wrapper = render(
57 |
58 | github.com
59 |
60 | );
61 |
62 | wrapper.rerender(
63 |
64 | github.com
65 |
66 | );
67 |
68 | expect(testContext.chartStubs.addCredits).toHaveBeenCalledWith(
69 | {
70 | href: 'https://www.github.com/whawker'
71 | },
72 | true
73 | );
74 | });
75 | });
76 |
77 | describe('when unmounted', () => {
78 | it('should disable the Credits', () => {
79 | const wrapper = render(github.com);
80 | wrapper.unmount();
81 | expect(testContext.chartStubs.addCredits).toHaveBeenCalledWith(
82 | {
83 | enabled: false
84 | },
85 | true
86 | );
87 | });
88 | });
89 | });
90 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/HighchartsChart/HighchartsChart.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Highcharts, createMockChart } from '../../test-utils';
5 | import HighchartsChart from '../../../src/components/HighchartsChart/HighchartsChart';
6 | import HighchartsContext from '../../../src/components/HighchartsContext';
7 |
8 | describe('', () => {
9 | let ProvidedHighchartsChart;
10 | let chart;
11 |
12 | beforeEach(() => {
13 | chart = createMockChart();
14 | Highcharts.chart.mockReturnValue(chart);
15 |
16 | ProvidedHighchartsChart = props => (
17 |
18 |
19 |
20 | );
21 | });
22 |
23 | afterEach(() => {
24 | Highcharts.chart.mockRestore();
25 | });
26 |
27 | it('creates a chart', () => {
28 | render();
29 |
30 | expect(Highcharts.chart).toHaveBeenCalled();
31 | });
32 |
33 | it('creates chart with the correct chart type', () => {
34 | render();
35 |
36 | expect(Highcharts.chart).toHaveBeenCalledWith(
37 | expect.anything(),
38 | expect.objectContaining({
39 | chartType: 'chart'
40 | })
41 | );
42 | });
43 |
44 | it('passes other props through to chart', () => {
45 | render();
46 |
47 | expect(Highcharts.chart).toHaveBeenCalledWith(
48 | expect.anything(),
49 | expect.objectContaining({
50 | plotOptions: { a: 'b' }
51 | })
52 | );
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Legend/Legend.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 | import Legend from '../../../src/components/Legend/Legend';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | describe('', () => {
9 | let testContext;
10 |
11 | let ProvidedLegend;
12 |
13 | beforeEach(() => {
14 | testContext = {};
15 | const { chartStubs, needsRedraw } = createMockProvidedChart();
16 |
17 | ProvidedLegend = props => (
18 |
19 |
20 |
21 | );
22 | testContext.chartStubs = chartStubs;
23 | testContext.needsRedraw = needsRedraw;
24 | });
25 |
26 | describe('when mounted', () => {
27 | it('add legend using the Highcharts update method', () => {
28 | render();
29 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
30 | {
31 | legend: {
32 | enabled: true
33 | }
34 | },
35 | false
36 | );
37 | expect(testContext.chartStubs.update).toHaveBeenCalledTimes(1);
38 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
39 | });
40 |
41 | it('updates the legend with the passed props', () => {
42 | render();
43 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
44 | {
45 | legend: {
46 | enabled: true,
47 | align: 'left',
48 | y: 20
49 | }
50 | },
51 | false
52 | );
53 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
54 | });
55 | });
56 |
57 | describe('update', () => {
58 | it('should use the update method when props change', () => {
59 | const wrapper = render();
60 | wrapper.rerender();
61 |
62 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
63 | {
64 | legend: {
65 | backgroundColor: 'red'
66 | }
67 | },
68 | false
69 | );
70 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(2);
71 | });
72 | });
73 |
74 | describe('when unmounted', () => {
75 | it('should disable the Legend', () => {
76 | const wrapper = render();
77 | wrapper.unmount();
78 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
79 | {
80 | legend: {
81 | enabled: false
82 | }
83 | },
84 | false
85 | );
86 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(2);
87 | });
88 | });
89 | });
90 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Legend/LegendTitle.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import LegendTitle from '../../../src/components/Legend/LegendTitle';
5 | import { createMockProvidedChart } from '../../test-utils';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | describe('', () => {
9 | let testContext;
10 | let ProvidedLegendTitle;
11 |
12 | beforeEach(() => {
13 | testContext = {};
14 | const { chartStubs, needsRedraw } = createMockProvidedChart();
15 | testContext.chartStubs = chartStubs;
16 |
17 | ProvidedLegendTitle = props => (
18 |
19 |
20 |
21 | );
22 | testContext.chartStubs = chartStubs;
23 | testContext.needsRedraw = needsRedraw;
24 | });
25 |
26 | describe('when mounted', () => {
27 | it('add legend using the Highcharts update method', () => {
28 | render(My Legend Title);
29 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
30 | {
31 | legend: {
32 | title: {
33 | text: 'My Legend Title'
34 | }
35 | }
36 | },
37 | false
38 | );
39 | });
40 |
41 | it('updates the legend with the passed props', () => {
42 | render(
43 |
44 | My Legend Title
45 |
46 | );
47 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
48 | {
49 | legend: {
50 | title: {
51 | text: 'My Legend Title',
52 | style: { color: 'red' }
53 | }
54 | }
55 | },
56 | false
57 | );
58 | });
59 | });
60 |
61 | describe('update', () => {
62 | it('should use the update method when props change', () => {
63 | const wrapper = render(
64 | My Legend Title
65 | );
66 | wrapper.rerender(
67 | My New Legend Title
68 | );
69 |
70 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
71 | {
72 | legend: {
73 | title: {
74 | text: 'My New Legend Title'
75 | }
76 | }
77 | },
78 | false
79 | );
80 | });
81 | });
82 |
83 | describe('when unmounted', () => {
84 | it('should disable the LegendTitle', () => {
85 | const wrapper = render(
86 | My Legend Title
87 | );
88 | wrapper.unmount();
89 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
90 | {
91 | legend: {
92 | title: {
93 | text: null
94 | }
95 | }
96 | },
97 | false
98 | );
99 | });
100 | });
101 | });
102 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Options3d/Options3d.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 | import Options3d from '../../../src/components/Options3d/Options3d';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | const defaultProps = {
9 | enabled: false,
10 | alpha: 0,
11 | beta: 0,
12 | depth: 100,
13 | fitToPlot: true,
14 | viewDistance: 25,
15 | axisLabelPosition: 'default',
16 | frame: {
17 | visible: 'default',
18 | size: 1,
19 | bottom: {},
20 | top: {},
21 | left: {},
22 | right: {},
23 | back: {},
24 | front: {}
25 | }
26 | };
27 |
28 | describe('', () => {
29 | let testContext;
30 | let ProvidedOptions3d;
31 |
32 | beforeEach(() => {
33 | testContext = {};
34 | const { chartStubs } = createMockProvidedChart();
35 | testContext.chartStubs = chartStubs;
36 | ProvidedOptions3d = props => (
37 |
38 |
39 |
40 | );
41 | });
42 |
43 | describe('when mounted', () => {
44 | it('updates the chart with the passed props', () => {
45 | render();
46 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
47 | {
48 | chart: {
49 | options3d: {
50 | ...defaultProps,
51 | enabled: true,
52 | alpha: 10,
53 | beta: 20
54 | }
55 | }
56 | },
57 | true
58 | );
59 | });
60 | });
61 |
62 | describe('update', () => {
63 | it('should use the update method when props change', () => {
64 | const wrapper = render();
65 | wrapper.rerender();
66 |
67 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
68 | {
69 | chart: {
70 | options3d: {
71 | ...defaultProps,
72 | enabled: true,
73 | alpha: 45
74 | }
75 | }
76 | },
77 | true
78 | );
79 | });
80 | });
81 | });
82 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Pane/Pane.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 | import Pane from '../../../src/components/Pane/Pane';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | describe('', () => {
9 | let testContext;
10 | let ProvidedPane;
11 | beforeEach(() => {
12 | testContext = {};
13 | const { chartStubs, needsRedraw } = createMockProvidedChart();
14 | testContext.chartStubs = chartStubs;
15 | testContext.needsRedraw = needsRedraw;
16 |
17 | ProvidedPane = props => (
18 |
19 |
20 |
21 | );
22 | });
23 |
24 | describe('when mounted', () => {
25 | it('set Pane options using the Highcharts update method', () => {
26 | render();
27 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
28 | {
29 | pane: {
30 | center: ['50%', '85%'],
31 | size: '100%'
32 | }
33 | },
34 | false
35 | );
36 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
37 | });
38 |
39 | it('does not add pane with empty props', () => {
40 | render();
41 | expect(testContext.chartStubs.update).not.toHaveBeenCalled();
42 | expect(testContext.needsRedraw).not.toHaveBeenCalled();
43 | });
44 | });
45 |
46 | describe('update', () => {
47 | it('should use the update method when props change', () => {
48 | const wrapper = render();
49 | wrapper.rerender();
50 |
51 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
52 | {
53 | pane: {
54 | size: '50%'
55 | }
56 | },
57 | false
58 | );
59 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
60 | });
61 | });
62 |
63 | describe('when unmounted', () => {
64 | it('should disable the Pane', () => {
65 | const wrapper = render();
66 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
67 | testContext.needsRedraw.mockClear();
68 | wrapper.unmount();
69 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
70 | {
71 | pane: {}
72 | },
73 | false
74 | );
75 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
76 | });
77 | });
78 | });
79 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/PlotBandLine/PlotBandLineLabel.integration.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Highcharts from 'highcharts';
3 | import addAccessibility from 'highcharts/modules/accessibility';
4 |
5 | import { render } from '@testing-library/react';
6 |
7 | import {
8 | HighchartsChart,
9 | HighchartsProvider,
10 | PlotBand,
11 | YAxis,
12 | XAxis,
13 | LineSeries
14 | } from '../../../src';
15 | import ContextSpy from '../../ContextSpy';
16 |
17 | addAccessibility(Highcharts);
18 |
19 | describe(' integration', () => {
20 | let axisRef;
21 | const DEFAULT_SERIES_DATA = [1, 2, 3, 4, 5];
22 | const Component = ({
23 | id,
24 | from,
25 | to,
26 | labelStyle,
27 | yaxisLabels,
28 | seriesData = DEFAULT_SERIES_DATA
29 | }) => {
30 | return (
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | );
44 | };
45 |
46 | beforeEach(() => {
47 | axisRef = { current: null };
48 | });
49 |
50 | describe('when parent axis is updated', () => {
51 | it('updates plotband style', () => {
52 | const wrapper = render(
53 |
59 | );
60 |
61 | let axis = axisRef.current && axisRef.current.object;
62 |
63 | wrapper.rerender(
64 |
70 | );
71 |
72 | expect(axis.plotLinesAndBands[0].options.label.style).toEqual({
73 | color: '#bbb'
74 | });
75 |
76 | wrapper.rerender(
77 |
83 | );
84 |
85 | expect(axis.plotLinesAndBands[0].options.label.style).toEqual({
86 | color: '#ccc'
87 | });
88 | });
89 | });
90 | });
91 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/PlotBandLine/PlotBandLineLabel.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import PlotBandLineLabel from '../../../src/components/PlotBandLine/PlotBandLineLabel';
5 | import PlotLineContext from '../../../src/components/PlotBandLineContext';
6 |
7 | describe('', () => {
8 | let testContext;
9 | let ProvidedPlotBandLineLabel;
10 | beforeEach(() => {
11 | testContext = {};
12 |
13 | testContext.plotLine = {
14 | id: 'myPlotLine',
15 | options: { label: { text: null } },
16 | render: jest.fn()
17 | };
18 | testContext.providedPlotline = {
19 | get object() {
20 | return testContext.plotLine;
21 | }
22 | };
23 | ProvidedPlotBandLineLabel = props => (
24 |
25 |
26 |
27 | );
28 | });
29 |
30 | describe('when mounted', () => {
31 | it('sets the correct plot line label', () => {
32 | render(
33 | My PlotLine Label
34 | );
35 |
36 | expect(testContext.plotLine.options.label).toEqual({
37 | text: 'My PlotLine Label'
38 | });
39 | expect(testContext.plotLine.render).toHaveBeenCalledTimes(1);
40 | });
41 |
42 | it('should pass additional props too', () => {
43 | render(
44 |
45 | My PlotLine Label
46 |
47 | );
48 |
49 | expect(testContext.plotLine.options.label).toEqual({
50 | text: 'My PlotLine Label',
51 | align: 'left'
52 | });
53 | expect(testContext.plotLine.render).toHaveBeenCalledTimes(1);
54 | });
55 |
56 | it('should pass formatter prop', () => {
57 | const formatter = () => 'My PlotLine Label';
58 | render();
59 |
60 | expect(testContext.plotLine.options.label).toEqual({
61 | formatter
62 | });
63 | expect(testContext.plotLine.render).toHaveBeenCalledTimes(1);
64 | });
65 | });
66 |
67 | describe('update', () => {
68 | it('should update the correct plot line if the component props change', () => {
69 | const wrapper = render(
70 |
71 | My PlotLine Label
72 |
73 | );
74 | testContext.plotLine.render.mockClear();
75 | wrapper.rerender(
76 |
77 | My New Label
78 |
79 | );
80 |
81 | expect(testContext.plotLine.options.label).toEqual({
82 | text: 'My New Label'
83 | });
84 | expect(testContext.plotLine.render).toHaveBeenCalledTimes(1);
85 | });
86 | });
87 |
88 | describe('when unmounted', () => {
89 | it('sets the correct plot line label text to null', () => {
90 | const wrapper = render(
91 |
92 | My PlotLine Label
93 |
94 | );
95 | testContext.plotLine.render.mockClear();
96 | wrapper.unmount();
97 |
98 | expect(testContext.plotLine.options.label).toEqual({
99 | text: null
100 | });
101 | expect(testContext.plotLine.render).toHaveBeenCalledTimes(1);
102 | });
103 | });
104 | });
105 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Series/Series.integration.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Highcharts from 'highcharts';
3 | import addAccessibility from 'highcharts/modules/accessibility';
4 |
5 | import { render } from '@testing-library/react';
6 |
7 | import {
8 | HighchartsChart,
9 | Chart,
10 | YAxis,
11 | XAxis,
12 | HighchartsProvider,
13 | Series
14 | } from '../../../src';
15 |
16 | import ContextSpy from '../../ContextSpy';
17 |
18 | addAccessibility(Highcharts);
19 |
20 | describe(' integration', () => {
21 | let Component;
22 | let seriesRef;
23 | beforeEach(() => {
24 | seriesRef = {};
25 |
26 | Component = props => {
27 | return (
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | };
41 | });
42 |
43 | it('fires onHide eventhandler', () => {
44 | const onHide = jest.fn();
45 |
46 | render();
47 | seriesRef.current.object.hide();
48 | expect(onHide).toHaveBeenCalled();
49 | });
50 |
51 | it('changes onHide eventhandler when new one is passed', () => {
52 | const onHide1 = jest.fn();
53 | const onHide2 = jest.fn();
54 |
55 | const wrapper = render();
56 |
57 | wrapper.rerender();
58 |
59 | seriesRef.current.object.hide();
60 | expect(onHide1).not.toHaveBeenCalled();
61 | expect(onHide2).toHaveBeenCalled();
62 | });
63 | });
64 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Series/SeriesTypes.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import ShallowRenderer from 'react-test-renderer/shallow';
3 |
4 | import * as all from '../../../src';
5 | import Series from '../../../src/components/Series';
6 |
7 | const skippedSeries = ['BarSeries'];
8 | const noAxisSeries = [
9 | 'FunnelSeries',
10 | 'PackedBubbleSeries',
11 | 'PieSeries',
12 | 'PyramidSeries',
13 | 'VariablePieSeries',
14 | 'VennSeries'
15 | ];
16 | const needParentSeries = ['BellCurveSeries', 'HistogramSeries', 'ParetoSeries'];
17 |
18 | Object.keys(all)
19 | .filter(name => /^[A-Z].*Series$/.test(name))
20 | .forEach(seriesName => {
21 | if (skippedSeries.includes(seriesName)) return;
22 |
23 | const seriesType = seriesName
24 | .substring(0, seriesName.indexOf('Series'))
25 | .toLowerCase();
26 | const SeriesComponent = all[seriesName]; // eslint-disable-line import/namespace
27 |
28 | let props = {};
29 | if (needParentSeries.includes(seriesName)) {
30 | props.baseSeries = 'myBaseSeries';
31 | }
32 |
33 | describe(`<${seriesName} />`, () => {
34 | let renderer;
35 | beforeEach(() => {
36 | renderer = new ShallowRenderer();
37 | });
38 |
39 | it('renders a ', () => {
40 | renderer.render();
41 | const result = renderer.getRenderOutput();
42 |
43 | expect(result.type).toBe(Series);
44 | });
45 |
46 | it(`renders a `, () => {
47 | renderer.render();
48 | const result = renderer.getRenderOutput();
49 |
50 | expect(result.props).toHaveProperty('type', seriesType);
51 | });
52 |
53 | it('passes Data props through to ', () => {
54 | renderer.render(
55 |
56 | );
57 | const result = renderer.getRenderOutput();
58 |
59 | expect(result.props).toHaveProperty('data', [1, 2, 3, 4]);
60 | });
61 |
62 | it('passes other props through to ', () => {
63 | renderer.render(
64 |
65 | );
66 | const result = renderer.getRenderOutput();
67 |
68 | expect(result.props).toHaveProperty('zIndex', -1);
69 | });
70 |
71 | if (noAxisSeries.includes(seriesName)) {
72 | it('does not require an axis', () => {
73 | renderer.render();
74 | const result = renderer.getRenderOutput();
75 |
76 | expect(result.props).toHaveProperty('requiresAxis', false);
77 | });
78 | }
79 | });
80 | });
81 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Subtitle/Subtitle.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 | import Subtitle from '../../../src/components/Subtitle/Subtitle';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | describe('', () => {
9 | let testContext;
10 | let ProvidedSubtitle;
11 |
12 | beforeEach(() => {
13 | testContext = {};
14 | const { chartStubs } = createMockProvidedChart();
15 | testContext.chartStubs = chartStubs;
16 |
17 | ProvidedSubtitle = props => (
18 |
19 |
20 |
21 | );
22 | });
23 |
24 | describe('when mounted', () => {
25 | it('adds a subtitle using the Highcharts setTitle method', () => {
26 | render(My Subtitle);
27 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledTimes(1);
28 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
29 | undefined,
30 | { text: 'My Subtitle' },
31 | false
32 | );
33 | });
34 |
35 | it('should pass additional props through to Highcharts setTitle method', () => {
36 | render(
37 | My Other Subtitle
38 | );
39 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
40 | undefined,
41 | { text: 'My Other Subtitle', align: 'right' },
42 | false
43 | );
44 | });
45 | });
46 |
47 | describe('update', () => {
48 | it('should use the setTitle method when the data changes', () => {
49 | const wrapper = render(My Subtitle);
50 | testContext.chartStubs.setTitle.mockClear();
51 | wrapper.rerender(
52 |
53 | My New Subtitle
54 |
55 | );
56 |
57 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledTimes(1);
58 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
59 | undefined,
60 | { x: 10, y: 20, text: 'My New Subtitle' },
61 | false
62 | );
63 | });
64 | });
65 |
66 | describe('when unmounted', () => {
67 | it('removes the subtitle by setting the subtitle to text', () => {
68 | const wrapper = render(My Subtitle);
69 | testContext.chartStubs.setTitle.mockClear();
70 | wrapper.unmount();
71 |
72 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledTimes(1);
73 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
74 | undefined,
75 | { text: null },
76 | false
77 | );
78 | });
79 | });
80 | });
81 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Title/Title.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 | import Title from '../../../src/components/Title/Title';
6 | import ChartContext from '../../../src/components/ChartContext';
7 |
8 | describe('', () => {
9 | let testContext;
10 | let ProvidedTitle;
11 |
12 | beforeEach(() => {
13 | testContext = {};
14 | const { chartStubs, needsRedraw } = createMockProvidedChart();
15 | testContext.chartStubs = chartStubs;
16 | testContext.needsRedraw = needsRedraw;
17 |
18 | ProvidedTitle = props => (
19 |
20 |
21 |
22 | );
23 | });
24 |
25 | describe('when mounted', () => {
26 | it('adds a title using the Highcharts setTitle method', () => {
27 | render(My Title);
28 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
29 | { text: 'My Title' },
30 | null,
31 | false
32 | );
33 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledTimes(1);
34 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(1);
35 | });
36 |
37 | it('should pass additional props through to Highcharts setTitle method', () => {
38 | render(My Other Title);
39 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
40 | { text: 'My Other Title', align: 'right' },
41 | null,
42 | false
43 | );
44 | });
45 | });
46 |
47 | describe('update', () => {
48 | it('should use the setTitle method when the data changes', () => {
49 | const wrapper = render(My Title);
50 | wrapper.rerender(
51 |
52 | My New Title
53 |
54 | );
55 |
56 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
57 | { x: 10, y: 20, text: 'My New Title' },
58 | null,
59 | false
60 | );
61 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(2);
62 | });
63 | });
64 |
65 | describe('when unmounted', () => {
66 | it('removes the title by setting the title to text', () => {
67 | const wrapper = render(My Title);
68 | wrapper.unmount();
69 | expect(testContext.chartStubs.setTitle).toHaveBeenCalledWith(
70 | { text: null },
71 | null,
72 | false
73 | );
74 | expect(testContext.needsRedraw).toHaveBeenCalledTimes(2);
75 | });
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/Tooltip/Tooltip.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { Highcharts, createMockProvidedChart } from '../../test-utils';
5 | import Tooltip from '../../../src/components/Tooltip/Tooltip';
6 | import HighchartsContext from '../../../src/components/HighchartsContext';
7 | import ChartContext from '../../../src/components/ChartContext';
8 |
9 | describe('', () => {
10 | let testContext;
11 | let ProvidedTooltip;
12 | beforeEach(() => {
13 | testContext = {};
14 |
15 | const { chartStubs } = createMockProvidedChart();
16 |
17 | testContext.chartStubs = chartStubs;
18 | testContext.chart = {};
19 | testContext.chartStubs.object = testContext.chart;
20 | ProvidedTooltip = props => (
21 |
22 |
23 |
24 |
25 |
26 | );
27 | });
28 |
29 | describe('when mounted', () => {
30 | it('enables the tooltip', () => {
31 | render();
32 | expect(testContext.chartStubs.update).toHaveBeenCalledWith({
33 | tooltip: { enabled: true }
34 | });
35 | });
36 |
37 | it('updates the chart with the passed props', () => {
38 | render();
39 |
40 | expect(testContext.chartStubs.update).toHaveBeenCalledWith({
41 | tooltip: { backgroundColor: 'red', enabled: true, shadow: false }
42 | });
43 | });
44 | });
45 |
46 | describe('update', () => {
47 | it('should use the update method when props change', () => {
48 | const wrapper = render();
49 | wrapper.rerender();
50 |
51 | expect(testContext.chartStubs.update).toHaveBeenCalledWith({
52 | tooltip: { padding: 2 }
53 | });
54 | });
55 | });
56 |
57 | describe('when unmounted', () => {
58 | it('should disable the Tooltip', () => {
59 | const wrapper = render();
60 | testContext.chartStubs.update.mockClear();
61 | wrapper.unmount();
62 |
63 | expect(testContext.chartStubs.update).toHaveBeenCalledTimes(1);
64 | expect(testContext.chartStubs.update).toHaveBeenCalledWith({
65 | tooltip: { enabled: false }
66 | });
67 | });
68 | });
69 | });
70 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UseAxis/useAxis.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import useAxis from '../../../src/components/UseAxis';
5 | import AxisContext from '../../../src/components/AxisContext';
6 | import ChartContext from '../../../src/components/ChartContext';
7 | import { createMockAxis } from '../../test-utils';
8 | import * as createProvidedAxis from '../../../src/components/Axis/createProvidedAxis';
9 |
10 | describe('useAxis', () => {
11 | let ChildComponent;
12 | let testAxis;
13 | let testChart;
14 | let axisCallback;
15 | beforeEach(() => {
16 | jest.useFakeTimers();
17 |
18 | testAxis = createMockAxis();
19 |
20 | testChart = {
21 | get: jest.fn().mockImplementation(() => testAxis)
22 | };
23 | axisCallback = jest.fn();
24 |
25 | jest.spyOn(createProvidedAxis, 'default').mockImplementation(c => c);
26 |
27 | ChildComponent = props => {
28 | const axis = useAxis(props.axisId);
29 | axisCallback(axis);
30 | return null;
31 | };
32 | });
33 |
34 | afterEach(() => {
35 | jest.clearAllTimers();
36 | });
37 |
38 | it('should return axis from context', () => {
39 | render(
40 |
41 |
42 |
43 | );
44 |
45 | expect(axisCallback).toHaveBeenCalledWith(testAxis);
46 | });
47 |
48 | it('should return axis outside the context', () => {
49 | render(
50 |
51 |
52 |
53 | );
54 |
55 | expect(testChart.get).toHaveBeenCalledWith('myAxisId');
56 | expect(axisCallback).toHaveBeenCalledWith(testAxis);
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UseChart/useChart.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import ChartContext from '../../../src/components/ChartContext';
5 |
6 | import ContextSpy from '../../ContextSpy';
7 |
8 | describe('useChart', () => {
9 | let ProvidedChartComponent;
10 | let testChart;
11 | let chartRef;
12 |
13 | beforeEach(() => {
14 | testChart = {};
15 | chartRef = {};
16 |
17 | ProvidedChartComponent = () => (
18 |
19 |
20 |
21 | );
22 | });
23 | it('should return chart from context', () => {
24 | render();
25 |
26 | expect(chartRef.current).toEqual(testChart);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UseChartUpdate/useChartUpdate.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import useChartUpdate from '../../../src/components/UseChartUpdate';
5 | import ChartContext from '../../../src/components/ChartContext';
6 | import { createMockProvidedChart } from '../../test-utils';
7 |
8 | describe('useChartUpdate', () => {
9 | let ProvidedChartComponent;
10 | let ChildComponent;
11 | let testChart;
12 | let updateFn;
13 | let destroyFn;
14 |
15 | beforeEach(() => {
16 | const { chartStubs } = createMockProvidedChart();
17 | testChart = chartStubs;
18 | updateFn = jest.fn();
19 | destroyFn = jest.fn();
20 |
21 | ChildComponent = props => {
22 | useChartUpdate(props, updateFn, destroyFn, false);
23 | return null;
24 | };
25 |
26 | ProvidedChartComponent = props => (
27 |
28 | testtext
29 |
30 | );
31 | });
32 |
33 | it('should call update function on mount', () => {
34 | render();
35 |
36 | expect(updateFn).toHaveBeenCalledWith(testChart, { firstProp: 'first' });
37 | expect(destroyFn).not.toHaveBeenCalled();
38 | });
39 |
40 | it('should call update function with modifiedProps', () => {
41 | const wrapper = render();
42 | updateFn.mockClear();
43 | wrapper.rerender(
44 |
45 | );
46 |
47 | expect(updateFn).toHaveBeenCalledWith(testChart, {
48 | firstProp: 'first2',
49 | secondProp: 'second'
50 | });
51 | expect(destroyFn).not.toHaveBeenCalled();
52 | });
53 |
54 | it("should not call update function when props don't change", () => {
55 | const wrapper = render();
56 |
57 | updateFn.mockClear();
58 | wrapper.rerender();
59 |
60 | expect(updateFn).not.toHaveBeenCalled();
61 | });
62 |
63 | it('should call destroy function on unmount', () => {
64 | const wrapper = render();
65 |
66 | updateFn.mockClear();
67 | wrapper.unmount();
68 |
69 | expect(destroyFn).toHaveBeenCalledWith(testChart);
70 | expect(updateFn).not.toHaveBeenCalled();
71 | });
72 | });
73 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UseHighcharts/useHighcharts.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import HighchartsContext from '../../../src/components/HighchartsContext';
5 | import { Highcharts } from '../../test-utils';
6 |
7 | import ContextSpy from '../../ContextSpy';
8 |
9 | describe('useHighcharts', () => {
10 | let ProvidedHighchartsComponent;
11 | let highchartsRef;
12 |
13 | beforeEach(() => {
14 | highchartsRef = {};
15 |
16 | ProvidedHighchartsComponent = () => (
17 |
18 |
19 |
20 | );
21 | });
22 | it('should return Highcharts from context', () => {
23 | render();
24 |
25 | expect(highchartsRef.current).toEqual(Highcharts);
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UseManualEventHandlers/useManualEventHandlers.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import useManualEventHandlers from '../../../src/components/UseManualEventHandlers';
5 |
6 | import { Highcharts } from '../../test-utils';
7 | import HighchartContext from '../../../src/components/HighchartsContext';
8 |
9 | describe('useManualEventHandlers', () => {
10 | let ProvidedComponent;
11 | let target;
12 |
13 | beforeEach(() => {
14 | target = new Object();
15 | const Component = props => {
16 | useManualEventHandlers(props, target);
17 | return ;
18 | };
19 | ProvidedComponent = props => (
20 |
21 |
22 |
23 | );
24 | });
25 |
26 | afterEach(() => {
27 | Highcharts.removeEvent.mockClear();
28 | Highcharts.addEvent.mockClear();
29 | });
30 |
31 | describe('when mounted', () => {
32 | it('should call the Highcharts.addEvent', () => {
33 | const onEventHandler = jest.fn();
34 | const onOtherEventHandler = jest.fn();
35 |
36 | const props = {
37 | enabled: true,
38 | onEventHandler,
39 | onOtherEventHandler,
40 | onNotAFunction: 'trip',
41 | something: 'stringy',
42 | count: 14
43 | };
44 |
45 | render();
46 |
47 | expect(Highcharts.removeEvent).not.toHaveBeenCalled();
48 | expect(Highcharts.addEvent).toHaveBeenCalledWith(
49 | target,
50 | 'eventHandler',
51 | onEventHandler
52 | );
53 | expect(Highcharts.addEvent).toHaveBeenCalledWith(
54 | target,
55 | 'otherEventHandler',
56 | onOtherEventHandler
57 | );
58 | expect(Highcharts.addEvent).not.toHaveBeenCalledWith(
59 | target,
60 | 'onNotAFunction',
61 | 'trip'
62 | );
63 | });
64 |
65 | it('should not call the Highcharts.addEvent when props is undefined', () => {
66 | render();
67 |
68 | expect(Highcharts.addEvent).not.toHaveBeenCalled();
69 | });
70 | });
71 |
72 | describe('when updated', () => {
73 | it('should call the Highcharts.removeEvent and addEvent with changed handlers', () => {
74 | const onEventHandler = jest.fn();
75 | const onOtherEventHandler = jest.fn();
76 | const onThirdEventHandler = jest.fn();
77 | const props = {
78 | onEventHandler,
79 | onOtherEventHandler,
80 | onThirdEventHandler
81 | };
82 |
83 | const wrapper = render();
84 | Highcharts.addEvent.mockClear();
85 | Highcharts.removeEvent.mockClear();
86 | const onNewOtherEventHandler = jest.fn();
87 |
88 | const updatedProps = {
89 | onEventHandler,
90 | onOtherEventHandler: onNewOtherEventHandler
91 | };
92 | wrapper.rerender();
93 |
94 | expect(Highcharts.removeEvent).not.toHaveBeenCalledWith(
95 | target,
96 | 'eventHandler',
97 | onEventHandler
98 | );
99 | expect(Highcharts.addEvent).not.toHaveBeenCalledWith(
100 | target,
101 | 'eventHandler',
102 | onEventHandler
103 | );
104 |
105 | expect(Highcharts.removeEvent).toHaveBeenCalledWith(
106 | target,
107 | 'otherEventHandler',
108 | onOtherEventHandler
109 | );
110 | expect(Highcharts.addEvent).toHaveBeenCalledWith(
111 | target,
112 | 'otherEventHandler',
113 | onNewOtherEventHandler
114 | );
115 | /* TODO removing eventhandlers completely fails.
116 | expect(Highcharts.removeEvent).toHaveBeenCalledWith(
117 | target,
118 | 'thirdEventHandler',
119 | onThirdEventHandler
120 | );
121 | */
122 | });
123 | });
124 | });
125 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UseModifiedProps/useModifiedProps.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import useModifiedProps from '../../../src/components/UseModifiedProps';
5 |
6 | describe('useChartUpdate', () => {
7 | let Component;
8 | let callback;
9 |
10 | beforeEach(() => {
11 | callback = jest.fn();
12 | Component = props => {
13 | const modifiedProps = useModifiedProps(props);
14 | callback(modifiedProps);
15 | return null;
16 | };
17 | });
18 |
19 | it('should return all props on initial mount', () => {
20 | render();
21 | expect(callback).toHaveBeenCalledWith({ someProp: true });
22 | });
23 |
24 | it('should return changed props', () => {
25 | const wrapper = render();
26 | callback.mockClear();
27 | wrapper.rerender();
28 |
29 | expect(callback).toHaveBeenCalledWith({ someProp: true });
30 | });
31 |
32 | it('should return false for not changed props', () => {
33 | const wrapper = render();
34 | callback.mockClear();
35 | wrapper.rerender();
36 |
37 | expect(callback).toHaveBeenCalledWith(false);
38 | });
39 |
40 | it('should return false for empty props', () => {
41 | render();
42 |
43 | expect(callback).toHaveBeenCalledWith(false);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UsePlotBandLine/usePlotBandLine.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import PlotBandLineContext from '../../../src/components/PlotBandLineContext';
5 |
6 | import ContextSpy from '../../ContextSpy';
7 |
8 | describe('usePlotBandLine', () => {
9 | let ProvidedPlotBandLineComponent;
10 | let testPlotBandLine;
11 | let plotBandLineRef;
12 |
13 | beforeEach(() => {
14 | testPlotBandLine = {};
15 | plotBandLineRef = {};
16 |
17 | ProvidedPlotBandLineComponent = () => (
18 |
19 |
20 |
21 | );
22 | });
23 | it('should return PlotBandLine from context', () => {
24 | render();
25 |
26 | expect(plotBandLineRef.current).toEqual(testPlotBandLine);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/UseSeries/useSeries.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import useSeries from '../../../src/components/UseSeries';
5 | import SeriesContext from '../../../src/components/SeriesContext';
6 | import ChartContext from '../../../src/components/ChartContext';
7 | import { createMockSeries } from '../../test-utils';
8 | import * as createProvidedSeries from '../../../src/components/Series/createProvidedSeries';
9 |
10 | describe('useSeries', () => {
11 | let ChildComponent;
12 | let testSeries;
13 | let testChart;
14 | let seriesCallback;
15 |
16 | beforeEach(() => {
17 | jest.useFakeTimers();
18 |
19 | testSeries = createMockSeries();
20 |
21 | testChart = {
22 | get: jest.fn().mockImplementation(() => testSeries)
23 | };
24 | seriesCallback = jest.fn();
25 |
26 | jest.spyOn(createProvidedSeries, 'default').mockImplementation(c => c);
27 |
28 | ChildComponent = props => {
29 | const axis = useSeries(props.seriesId);
30 | seriesCallback(axis);
31 | return null;
32 | };
33 | });
34 |
35 | afterEach(() => {
36 | jest.clearAllTimers();
37 | });
38 |
39 | it('should return series from context', () => {
40 | render(
41 |
42 |
43 |
44 | );
45 |
46 | expect(seriesCallback).toHaveBeenCalledWith(testSeries);
47 | });
48 |
49 | it('should return series outside the context', () => {
50 | render(
51 |
52 |
53 |
54 | );
55 |
56 | expect(testChart.get).toHaveBeenCalledWith('mySeriesId');
57 | expect(seriesCallback).toHaveBeenCalledWith(testSeries);
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/WithHighcharts/index.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import withHighcharts from '../../../src/components/WithHighcharts';
5 | import { Highcharts } from '../../test-utils';
6 | import ContextSpy from '../../ContextSpy';
7 |
8 | describe('withHighcharts', () => {
9 | let highchartsRef;
10 | let WrappedComponent;
11 |
12 | beforeEach(() => {
13 | highchartsRef = {};
14 |
15 | WrappedComponent = () => ;
16 | });
17 |
18 | it('should create Highcharts context with the provided object', () => {
19 | const WithHighchartsComponent = withHighcharts(
20 | WrappedComponent,
21 | Highcharts
22 | );
23 | render();
24 |
25 | expect(highchartsRef.current).toEqual(Highcharts);
26 | });
27 |
28 | it('should create a Highcharts context with the provided object (2)', () => {
29 | const HighchartsWithExtraFunctionality = {
30 | ...Highcharts,
31 | Extras: () => 'Extras'
32 | };
33 | const WithHighchartsComponent = withHighcharts(
34 | WrappedComponent,
35 | HighchartsWithExtraFunctionality
36 | );
37 | render();
38 |
39 | expect(highchartsRef.current).toEqual(HighchartsWithExtraFunctionality);
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/WithSeriesType/index.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import ShallowRenderer from 'react-test-renderer/shallow';
3 |
4 | import withSeriesType from '../../../src/components/WithSeriesType';
5 | import Series from '../../../src/components/Series';
6 |
7 | describe('withSeriesType', () => {
8 | let renderer;
9 |
10 | beforeEach(() => {
11 | renderer = new ShallowRenderer();
12 | });
13 |
14 | it('should create Series component', () => {
15 | const SeriesComponent = withSeriesType('line');
16 | renderer.render();
17 | const result = renderer.getRenderOutput();
18 |
19 | expect(result.type).toEqual(Series);
20 | });
21 |
22 | it(`should set type attribute `, () => {
23 | const SeriesComponent = withSeriesType('line');
24 | renderer.render();
25 | const result = renderer.getRenderOutput();
26 |
27 | expect(result.props).toHaveProperty('type', 'line');
28 | });
29 |
30 | it(`the created component should pass additional props through to Series`, () => {
31 | const SeriesComponent = withSeriesType('line');
32 | renderer.render();
33 | const result = renderer.getRenderOutput();
34 |
35 | expect(result.props).toHaveProperty('data', [1, 2, 3, 4]);
36 | });
37 |
38 | it(`should pass additionalProps to Series`, () => {
39 | const SeriesComponent = withSeriesType('line', { requiresAxis: false });
40 | renderer.render();
41 | const result = renderer.getRenderOutput();
42 |
43 | expect(result.props).toHaveProperty('requiresAxis', false);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/YAxis/YAxis.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import ShallowRenderer from 'react-test-renderer/shallow';
3 |
4 | import YAxis from '../../../src/components/YAxis/YAxis';
5 | import Axis from '../../../src/components/Axis';
6 |
7 | describe('', () => {
8 | let renderer;
9 |
10 | beforeEach(() => {
11 | renderer = new ShallowRenderer();
12 | });
13 |
14 | it('renders an ', () => {
15 | renderer.render();
16 | const result = renderer.getRenderOutput();
17 |
18 | expect(result.type).toEqual(Axis);
19 | });
20 |
21 | it('renders an ', () => {
22 | renderer.render();
23 | const result = renderer.getRenderOutput();
24 |
25 | expect(result.props).toHaveProperty('isX', false);
26 | });
27 |
28 | it('passes other props through to ', () => {
29 | renderer.render();
30 | const result = renderer.getRenderOutput();
31 |
32 | expect(result.props).toHaveProperty('tickLength', 1337);
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/components/ZAxis/ZAxis.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import ShallowRenderer from 'react-test-renderer/shallow';
3 |
4 | import ZAxis from '../../../src/components/ZAxis/ZAxis';
5 | import Axis from '../../../src/components/Axis';
6 |
7 | describe('', () => {
8 | let renderer;
9 |
10 | beforeEach(() => {
11 | renderer = new ShallowRenderer();
12 | });
13 |
14 | it('renders an ', () => {
15 | renderer.render();
16 | const result = renderer.getRenderOutput();
17 |
18 | expect(result.type).toEqual(Axis);
19 | });
20 |
21 | it('should always have the id `zAxis`', () => {
22 | renderer.render();
23 | const result = renderer.getRenderOutput();
24 |
25 | expect(result.props).toHaveProperty('id', 'zAxis');
26 | });
27 |
28 | it('should NOT be a dynamic axis', () => {
29 | renderer.render();
30 | const result = renderer.getRenderOutput();
31 |
32 | expect(result.props).toHaveProperty('dynamicAxis', false);
33 | });
34 |
35 | it('renders an ', () => {
36 | renderer.render();
37 | const result = renderer.getRenderOutput();
38 |
39 | expect(result.props).toHaveProperty('isX', false);
40 | });
41 |
42 | it('passes other props through to ', () => {
43 | renderer.render();
44 | const result = renderer.getRenderOutput();
45 |
46 | expect(result.props).toHaveProperty('tickLength', 1337);
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/test-helper.js:
--------------------------------------------------------------------------------
1 | // test setup here
2 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/test-utils.js:
--------------------------------------------------------------------------------
1 | export const uuidRegex =
2 | /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
3 |
4 | export const Highcharts = {
5 | chart: jest.fn(),
6 | addEvent: jest.fn(),
7 | removeEvent: jest.fn(),
8 | Tooltip: jest.fn().mockImplementation(() => ({ update: jest.fn() }))
9 | };
10 |
11 | export const createMockChart = () => ({
12 | addAxis: jest.fn(),
13 | addColorAxis: jest.fn(),
14 | addSeries: jest.fn(),
15 | get: jest.fn(),
16 | setSize: jest.fn(),
17 | update: jest.fn(),
18 | setTitle: jest.fn(),
19 | destroy: jest.fn(),
20 | showLoading: jest.fn(),
21 | hideLoading: jest.fn(),
22 | addCredits: jest.fn(),
23 | redraw: jest.fn(),
24 | setCaption: jest.fn()
25 | });
26 |
27 | export const createMockProvidedChart = () => {
28 | const chartStubs = createMockChart();
29 | chartStubs.needsRedraw = jest.fn();
30 | return {
31 | chartStubs,
32 | needsRedraw: chartStubs.needsRedraw
33 | };
34 | };
35 |
36 | export const createMockAxis = ({ ...additional } = {}) => ({
37 | ...additional,
38 | remove: jest.fn(),
39 | addPlotBandOrLine: jest
40 | .fn()
41 | .mockImplementation(() => ({ options: {}, render: jest.fn() })),
42 | removePlotBandOrLine: jest.fn(),
43 | getExtremes: jest.fn(),
44 | setExtremes: jest.fn(),
45 | update: jest.fn(),
46 | setTitle: jest.fn(),
47 | plotLinesAndBands: []
48 | });
49 |
50 | export const createMockProvidedAxis = ({ object, ...additional }) => {
51 | const axisStubs = createMockAxis(additional);
52 |
53 | return {
54 | axisStubs,
55 | providedAxis: {
56 | object,
57 | ...additional,
58 | ...axisStubs
59 | }
60 | };
61 | };
62 |
63 | export const createMockSeries = ({ ...additional } = {}) => ({
64 | ...additional,
65 | remove: jest.fn(),
66 | setData: jest.fn(),
67 | setVisible: jest.fn(),
68 | update: jest.fn()
69 | });
70 |
71 | export const createMockProvidedSeries = ({ object, ...additional }) => {
72 | const seriesStubs = createMockSeries(additional);
73 |
74 | return {
75 | seriesStubs,
76 | getSeries: () => ({
77 | object,
78 | ...additional,
79 | ...seriesStubs
80 | })
81 | };
82 | };
83 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/utils/events.spec.js:
--------------------------------------------------------------------------------
1 | import * as events from '../../src/utils/events';
2 | import { Highcharts } from '../test-utils';
3 |
4 | describe('utils/events', () => {
5 | beforeEach(() => {
6 | Highcharts.addEvent.mockClear();
7 | Highcharts.removeEvent.mockClear();
8 | });
9 |
10 | describe('getEventHandlerProps', () => {
11 | const { getEventHandlerProps } = events;
12 |
13 | it('should return all props that look like an event handler', () => {
14 | const onEventHandler = jest.fn();
15 | const onOtherEventHandler = jest.fn();
16 |
17 | const config = {
18 | enabled: true,
19 | onEventHandler,
20 | onOtherEventHandler,
21 | onNotAFunction: 'trip',
22 | something: 'stringy',
23 | count: 14
24 | };
25 |
26 | expect(getEventHandlerProps(config)).toEqual({
27 | onEventHandler,
28 | onOtherEventHandler
29 | });
30 | });
31 | });
32 |
33 | describe('getNonEventHandlerProps', () => {
34 | const { getNonEventHandlerProps } = events;
35 |
36 | it("should return all props that don't look like an event handler", () => {
37 | const config = {
38 | enabled: true,
39 | onEventHandler: jest.fn(),
40 | onOtherEventHandler: jest.fn(),
41 | onNotAFunction: 'trip',
42 | something: 'stringy',
43 | count: 14
44 | };
45 |
46 | expect(getNonEventHandlerProps(config)).toEqual({
47 | enabled: true,
48 | something: 'stringy',
49 | onNotAFunction: 'trip',
50 | count: 14
51 | });
52 | });
53 | });
54 |
55 | describe('getEventsConfig', () => {
56 | const { getEventsConfig } = events;
57 |
58 | it('should return all props that look like an event handler, without the `on` prefix', () => {
59 | const onEventHandler = jest.fn();
60 | const onOtherEventHandler = jest.fn();
61 |
62 | const config = {
63 | enabled: true,
64 | onEventHandler,
65 | onOtherEventHandler,
66 | onNotAFunction: 'trip',
67 | something: 'stringy',
68 | count: 14
69 | };
70 |
71 | expect(getEventsConfig(config)).toEqual({
72 | eventHandler: onEventHandler,
73 | otherEventHandler: onOtherEventHandler
74 | });
75 | });
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/utils/getModifiedProps.spec.js:
--------------------------------------------------------------------------------
1 | import getModifiedProps from '../../src/utils/getModifiedProps';
2 |
3 | describe('utils/getModifiedProps', () => {
4 | it('should return only modified props', () => {
5 | const prevProps = {
6 | firstProp: true,
7 | secondProp: true
8 | };
9 |
10 | const currProps = {
11 | firstProp: true,
12 | secondProp: false
13 | };
14 |
15 | const returnedProps = getModifiedProps(prevProps, currProps, false);
16 | expect(returnedProps).toEqual({ secondProp: false });
17 | });
18 |
19 | it('should return false for non modified props', () => {
20 | const prevProps = {
21 | firstProp: true,
22 | secondProp: true
23 | };
24 |
25 | const returnedProps = getModifiedProps(prevProps, prevProps, false);
26 | expect(returnedProps).toEqual(false);
27 | });
28 |
29 | it('should return added props', () => {
30 | const prevProps = {
31 | firstProp: true
32 | };
33 |
34 | const currProps = {
35 | secondProp: false
36 | };
37 |
38 | const returnedProps = getModifiedProps(prevProps, currProps, false);
39 | expect(returnedProps).toEqual({ secondProp: false });
40 | });
41 |
42 | it('should return modified props for undefined prevProps', () => {
43 | const prevProps = undefined;
44 |
45 | const currProps = {
46 | firstProp: true,
47 | secondProp: false
48 | };
49 |
50 | const returnedProps = getModifiedProps(prevProps, currProps, false);
51 | expect(returnedProps).toEqual(currProps);
52 | });
53 |
54 | it('should return modified props for null prevProps', () => {
55 | const prevProps = null;
56 |
57 | const currProps = {
58 | firstProp: true,
59 | secondProp: false
60 | };
61 |
62 | const returnedProps = getModifiedProps(prevProps, currProps, false);
63 | expect(returnedProps).toEqual(currProps);
64 | });
65 | it('should not return text when children is not defined', () => {
66 | const prevProps = null;
67 |
68 | const currProps = {
69 | a: 1
70 | };
71 |
72 | const returnedProps = getModifiedProps(prevProps, currProps, true);
73 | expect(returnedProps.text).not.toBeDefined();
74 | expect(returnedProps.a).toBe(1);
75 | });
76 |
77 | it('should return text when children changes', () => {
78 | const prevProps = {};
79 |
80 | const currProps = {
81 | children: 'teststring'
82 | };
83 |
84 | const returnedProps = getModifiedProps(prevProps, currProps, true);
85 | expect(returnedProps.text).toBe('teststring');
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/test/utils/pickBy.spec.js:
--------------------------------------------------------------------------------
1 | import pickBy from '../../src/utils/pickBy';
2 |
3 | describe('utils/pickBy', () => {
4 | it('should return object which satisfies filter function', () => {
5 | const onInit = jest.fn();
6 | const props = {
7 | onInit,
8 | noPassed: false
9 | };
10 | const pickedProps = pickBy(props, key => {
11 | return key === 'onInit';
12 | });
13 |
14 | expect(pickedProps).toEqual({ onInit });
15 | });
16 |
17 | it('should return empty object for undefined object', () => {
18 | const pickedProps = pickBy(undefined, key => {
19 | return key === 'onInit';
20 | });
21 |
22 | expect(pickedProps).toEqual({});
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "node",
4 | "noImplicitAny": true,
5 | "target": "ES2020"
6 | },
7 | "include": ["./types/**/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/react-jsx-highcharts/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const path = require('path');
3 |
4 | const isProd = process.env.NODE_ENV === 'production';
5 |
6 | const webpackConfig = {
7 | mode: 'development',
8 |
9 | entry: path.resolve(__dirname, 'src'),
10 |
11 | output: {
12 | filename: isProd
13 | ? 'react-jsx-highcharts.min.js'
14 | : 'react-jsx-highcharts.js',
15 | path: path.resolve(__dirname, 'dist'),
16 | library: 'ReactHighcharts',
17 | libraryTarget: 'umd',
18 | // Prevents webpack from referencing `window` in the UMD build
19 | // Source: https://git.io/vppgU
20 | globalObject: "typeof self !== 'undefined' ? self : this"
21 | },
22 |
23 | externals: {
24 | react: {
25 | commonjs: 'react',
26 | commonjs2: 'react',
27 | amd: 'react',
28 | root: 'React'
29 | },
30 | 'react-dom': {
31 | commonjs: 'react-dom',
32 | commonjs2: 'react-dom',
33 | amd: 'react-dom',
34 | root: 'ReactDOM'
35 | },
36 | highcharts: {
37 | commonjs: 'highcharts',
38 | commonjs2: 'highcharts',
39 | amd: 'highcharts',
40 | root: 'Highcharts'
41 | }
42 | },
43 |
44 | module: {
45 | rules: [
46 | {
47 | test: /\.js$/,
48 | loader: 'babel-loader',
49 | exclude: /node_modules/
50 | }
51 | ]
52 | }
53 | };
54 |
55 | if (isProd) {
56 | webpackConfig.mode = 'production';
57 | }
58 |
59 | module.exports = webpackConfig;
60 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/.babelrc:
--------------------------------------------------------------------------------
1 | { "extends": "../../babel.config.js" }
2 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/jest.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | // For a detailed explanation regarding each configuration property, visit:
3 | // https://jestjs.io/docs/en/configuration.html
4 |
5 | /** @type {import('@jest/types').Config.InitialOptions} */
6 | const config = {
7 | testEnvironment: 'jsdom',
8 | setupFilesAfterEnv: ['/test/test-helper.js'],
9 | testMatch: ['**/test/**/*.spec.js?(x)']
10 | };
11 |
12 | module.exports = config;
13 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-jsx-highmaps",
3 | "version": "3.0.0",
4 | "description": "Highmaps built using React components",
5 | "main": "dist/react-jsx-highmaps.min.js",
6 | "module": "dist/es/index.js",
7 | "sideEffects": false,
8 | "files": [
9 | "dist",
10 | "src",
11 | "types"
12 | ],
13 | "scripts": {
14 | "build": "cross-env NODE_ENV=development webpack",
15 | "build:prod": "npm run build:umd && npm run build:es",
16 | "build:umd": "cross-env NODE_ENV=production webpack",
17 | "build:es": "cross-env BABEL_ENV=es babel src --out-dir dist/es",
18 | "clean": "rimraf dist",
19 | "format": "prettier --write \"src/**/*.js\" \"test/**/*.js\" README.md",
20 | "lint": "eslint src",
21 | "test": "jest",
22 | "test:coverage": "jest --coverage",
23 | "test:types": "tsc --noEmit"
24 | },
25 | "author": "Will Hawker",
26 | "contributors": [],
27 | "license": "MIT",
28 | "repository": {
29 | "type": "git",
30 | "url": "https://github.com/whawker/react-jsx-highcharts.git"
31 | },
32 | "bugs": "https://github.com/whawker/react-jsx-highcharts/issues",
33 | "homepage": "https://github.com/whawker/react-jsx-highcharts",
34 | "keywords": [
35 | "react",
36 | "reactjs",
37 | "react-component",
38 | "highcharts",
39 | "highmaps",
40 | "chart",
41 | "charts",
42 | "graphs",
43 | "visualization",
44 | "data",
45 | "maps"
46 | ],
47 | "dependencies": {
48 | "react-jsx-highcharts": "5.0.0"
49 | },
50 | "peerDependencies": {
51 | "highcharts": "^9.1.2 || ^10.0.0",
52 | "react": "^17.0.0 || ^18.0.0",
53 | "react-dom": "^17.0.0 || ^18.0.0"
54 | },
55 | "types": "types/index.d.ts",
56 | "browserslist": [
57 | "chrome >= 81",
58 | "edge >= 81",
59 | "firefox >= 78",
60 | "ios >= 12",
61 | "safari >= 12"
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/HighchartsMapChart/HighchartsMapChart.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useMemo, useCallback } from 'react';
3 | import { BaseChart, useHighcharts } from 'react-jsx-highcharts';
4 |
5 | const XAXIS = { id: 'xAxis' };
6 | const YAXIS = { id: 'yAxis' };
7 | const MAP_NAVIGATION = { enabled: false };
8 |
9 | const HighchartsMapChart = ({ map, chart, callback, ...restProps }) => {
10 | const Highcharts = useHighcharts();
11 | const geojson = useMemo(() => {
12 | return createGeoJSON(map, Highcharts);
13 | }, [map]);
14 | const chartConfig = useMemo(
15 | () => ({ ...chart, map: geojson }),
16 | [geojson, chart]
17 | );
18 |
19 | const chartCallback = useCallback(
20 | cbChart => {
21 | if (geojson) {
22 | const format = Highcharts.format;
23 | const { mapText, mapTextFull } = cbChart.options.credits;
24 | cbChart.mapCredits = format(mapText, { geojson });
25 | cbChart.mapCreditsFull = format(mapTextFull, { geojson });
26 | }
27 |
28 | if (callback) callback(cbChart);
29 | },
30 | [callback]
31 | );
32 |
33 | return (
34 |
44 | );
45 | };
46 |
47 | const createGeoJSON = (map, Highcharts) => {
48 | if (!map) return;
49 |
50 | return typeof map === 'string' ? Highcharts.maps[map] : map;
51 | };
52 | export default HighchartsMapChart;
53 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/HighchartsMapChart/index.js:
--------------------------------------------------------------------------------
1 | import HighchartsMapChart from './HighchartsMapChart';
2 | export default HighchartsMapChart;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/MapNavigation/MapNavigation.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useEffect, useState } from 'react';
3 | import {
4 | useModifiedProps,
5 | useChart,
6 | useHighcharts
7 | } from 'react-jsx-highcharts';
8 |
9 | const MapNavigation = ({ children, enabled = true, ...restProps }) => {
10 | const [rendered, setRendered] = useState(false);
11 | const chart = useChart();
12 | const Highcharts = useHighcharts();
13 |
14 | useEffect(() => {
15 | // Workaround inferred from http://jsfiddle.net/x40me94t/2/
16 | const chartObj = chart.object;
17 | chartObj.options.mapNavigation.enabled = true;
18 | // Initialise MapNavigation https://github.com/highcharts/highcharts/blob/dd730ab/js/parts-map/MapNavigation.js#L288-L294
19 | Highcharts.fireEvent(chartObj, 'beforeRender');
20 |
21 | const opts = getMapNavigationConfig({ enabled, ...restProps }, Highcharts);
22 | updateMapNavigation(opts, chart);
23 |
24 | setRendered(true);
25 |
26 | return () => {
27 | try {
28 | updateMapNavigation({ enabled: false }, chart);
29 | } catch {
30 | // ignore as chart might have already been unmounted
31 | }
32 | };
33 | }, []);
34 |
35 | const modifiedProps = useModifiedProps({ enabled, ...restProps });
36 |
37 | useEffect(() => {
38 | if (!rendered) return;
39 | if (modifiedProps !== false) {
40 | updateMapNavigation(modifiedProps, chart);
41 | }
42 | });
43 |
44 | if (!children || !rendered) return null;
45 |
46 | return <>{children}>;
47 | };
48 | const getMapNavigationConfig = (props, Highcharts) => {
49 | return {
50 | ...(Highcharts.defaultOptions && Highcharts.defaultOptions.mapNavigation),
51 | ...props,
52 | enableButtons: false,
53 | buttons: {
54 | zoomIn: {},
55 | zoomOut: {}
56 | }
57 | };
58 | };
59 |
60 | const updateMapNavigation = (config, chart) => {
61 | chart.update({ mapNavigation: config }, true);
62 | };
63 |
64 | export default MapNavigation;
65 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/MapNavigation/MapNavigationButton.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { useHighcharts, useChart } from 'react-jsx-highcharts';
3 |
4 | const MapNavigationButton = props => {
5 | const Highcharts = useHighcharts();
6 | const chart = useChart();
7 |
8 | useEffect(() => {
9 | const { type, ...rest } = props;
10 | const opts = getMapNavigationButtonConfig(rest, Highcharts);
11 | updateMapNavigationButton(type, opts, chart);
12 |
13 | return () => {
14 | // TODO removeButton was missing in original class?
15 | //const { type } = props;
16 | //attempt(this.removeButton, type, {});
17 | };
18 | }, []);
19 |
20 | return null;
21 | };
22 | const getMapNavigationButtonConfig = (props, Highcharts) => {
23 | const { children: text, onClick: onclick, ...rest } = props;
24 |
25 | return {
26 | ...(Highcharts.defaultOptions &&
27 | Highcharts.defaultOptions.mapNavigation.buttonOptions),
28 | onclick, // Weird Highcharts inconsistency, onclick instead of events: { click }
29 | ...rest,
30 | text
31 | };
32 | };
33 |
34 | const updateMapNavigationButton = (type, config, chart) => {
35 | const enableButtons = Object.keys(config).length > 0;
36 |
37 | chart.update({
38 | mapNavigation: {
39 | enableButtons,
40 | buttons: {
41 | [type]: config
42 | }
43 | }
44 | });
45 | };
46 |
47 | export default MapNavigationButton;
48 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/MapNavigation/MapNavigationZoomIn.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import MapNavigationButton from './MapNavigationButton';
3 |
4 | const DEFAULT_ONCLICK = function () {
5 | this.mapZoom(0.5);
6 | };
7 |
8 | const MapNavigationZoomIn = ({
9 | children = '+',
10 | onClick = DEFAULT_ONCLICK,
11 | y = 0,
12 | ...restProps
13 | }) => (
14 |
15 | {children}
16 |
17 | );
18 |
19 | export default MapNavigationZoomIn;
20 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/MapNavigation/MapNavigationZoomOut.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import MapNavigationButton from './MapNavigationButton';
3 |
4 | const DEFAULT_ONCLICK = function () {
5 | this.mapZoom(2);
6 | };
7 |
8 | const MapNavigationZoomOut = ({
9 | children = '-',
10 | onClick = DEFAULT_ONCLICK,
11 | y = 28,
12 | ...restProps
13 | }) => (
14 |
15 | {children}
16 |
17 | );
18 |
19 | export default MapNavigationZoomOut;
20 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/MapNavigation/index.js:
--------------------------------------------------------------------------------
1 | import MapNavigation from './MapNavigation';
2 | import MapNavigationZoomIn from './MapNavigationZoomIn';
3 | import MapNavigationZoomOut from './MapNavigationZoomOut';
4 | const ChartMapNavigation = MapNavigation;
5 | ChartMapNavigation.ZoomIn = MapNavigationZoomIn;
6 | ChartMapNavigation.ZoomOut = MapNavigationZoomOut;
7 | export default ChartMapNavigation;
8 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/XAxis/XAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { XAxis } from 'react-jsx-highcharts';
3 |
4 | const MapXAxis = ({
5 | endOnTick = false,
6 | visible = false,
7 | minPadding = 0,
8 | maxPadding = 0,
9 | startOnTick = false,
10 | ...restProps
11 | }) => (
12 |
22 | );
23 |
24 | export default MapXAxis;
25 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/XAxis/index.js:
--------------------------------------------------------------------------------
1 | import XAxis from './XAxis';
2 | export default XAxis;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/YAxis/YAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { YAxis } from 'react-jsx-highcharts';
3 |
4 | const MapYAxis = ({
5 | endOnTick = false,
6 | visible = false,
7 | minPadding = 0,
8 | maxPadding = 0,
9 | startOnTick = false,
10 | reversed = true,
11 | ...restProps
12 | }) => (
13 |
24 | );
25 |
26 | export default MapYAxis;
27 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/components/YAxis/index.js:
--------------------------------------------------------------------------------
1 | import YAxis from './YAxis';
2 | export default YAxis;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/src/index.js:
--------------------------------------------------------------------------------
1 | import { withSeriesType } from 'react-jsx-highcharts';
2 | export {
3 | Chart,
4 | ColorAxis,
5 | Credits,
6 | Debug,
7 | HighchartsProvider as HighmapsProvider,
8 | Loading,
9 | Legend,
10 | Series,
11 | Subtitle,
12 | Title,
13 | Tooltip,
14 | useHighcharts,
15 | useChart,
16 | useAxis,
17 | useSeries,
18 | withHighcharts as withHighmaps,
19 | withSeriesType
20 | } from 'react-jsx-highcharts';
21 |
22 | // Charts
23 | export { default as HighchartsMapChart } from './components/HighchartsMapChart';
24 |
25 | // Graph Parts
26 | export { default as MapNavigation } from './components/MapNavigation';
27 | export { default as XAxis } from './components/XAxis';
28 | export { default as YAxis } from './components/YAxis';
29 |
30 | // Series
31 | const parentAxisId = { axisId: 'yAxis' };
32 | export const MapBubbleSeries = withSeriesType('MapBubble', parentAxisId);
33 | export const MapLineSeries = withSeriesType('MapLine', parentAxisId);
34 | export const MapPointSeries = withSeriesType('MapPoint', parentAxisId);
35 | export const MapSeries = withSeriesType('Map', parentAxisId);
36 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/test/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | "jest": true
5 | },
6 | "rules": {
7 | "no-unused-vars": ["warn"],
8 | "react-perf/jsx-no-new-function-as-prop": "off",
9 | "react-perf/jsx-no-new-object-as-prop": "off",
10 | "react-perf/jsx-no-new-array-as-prop": "off",
11 | "react/display-name": "off"
12 | },
13 | "globals": {
14 | "mount": true,
15 | "shallow": true,
16 | "render": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/test/components/HighchartsMapChart/HighchartsMapChart.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | jest.mock('react-jsx-highcharts', () => ({
5 | ...jest.requireActual('react-jsx-highcharts'),
6 | useHighcharts: jest.fn()
7 | }));
8 |
9 | import { useHighcharts } from 'react-jsx-highcharts';
10 | import { Highcharts, createMockChart } from '../../test-utils';
11 | import HighchartsMapChart from '../../../src/components/HighchartsMapChart/HighchartsMapChart';
12 |
13 | describe('', () => {
14 | let chart;
15 |
16 | beforeEach(() => {
17 | chart = createMockChart();
18 | Highcharts.mapChart.mockReturnValue(chart);
19 | useHighcharts.mockImplementation(() => Highcharts);
20 | });
21 |
22 | afterEach(() => {
23 | Highcharts.mapChart.mockRestore();
24 | });
25 |
26 | it('creates a chart', () => {
27 | render();
28 |
29 | expect(Highcharts.mapChart).toHaveBeenCalled();
30 | });
31 |
32 | it('creates a chart with the correct chart type', () => {
33 | render();
34 |
35 | expect(Highcharts.mapChart).toHaveBeenCalledWith(
36 | expect.anything(),
37 | expect.objectContaining({
38 | chartType: 'mapChart'
39 | })
40 | );
41 | });
42 |
43 | it('creates a chart with GeoJSON from a string', () => {
44 | render();
45 |
46 | expect(Highcharts.mapChart).toHaveBeenCalledWith(
47 | expect.anything(),
48 | expect.objectContaining({
49 | chart: expect.objectContaining({ map: { some: 'data' } })
50 | })
51 | );
52 | });
53 |
54 | it('creates a chart with direct GeoJSON', () => {
55 | render();
56 |
57 | expect(Highcharts.mapChart).toHaveBeenCalledWith(
58 | expect.anything(),
59 | expect.objectContaining({
60 | chart: expect.objectContaining({ map: { direct: 'input' } })
61 | })
62 | );
63 | });
64 |
65 | it('passes other props through to chart', () => {
66 | render();
67 |
68 | expect(Highcharts.mapChart).toHaveBeenCalledWith(
69 | expect.anything(),
70 | expect.objectContaining({ plotOptions: { c: 'd' } })
71 | );
72 | });
73 |
74 | it('return a chart instance to the callback prop', () => {
75 | let cbChart;
76 | const chartCallback = returnedChart => {
77 | cbChart = returnedChart;
78 | };
79 | render();
80 | expect(cbChart).toBeDefined();
81 | });
82 | });
83 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/test/components/XAxis/XAxis.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import ShallowRenderer from 'react-test-renderer/shallow';
3 |
4 | import { XAxis } from 'react-jsx-highcharts';
5 | import MapXAxis from '../../../src/components/XAxis';
6 |
7 | describe('', () => {
8 | let renderer;
9 |
10 | beforeEach(() => {
11 | renderer = new ShallowRenderer();
12 | });
13 |
14 | it('renders an ', () => {
15 | renderer.render();
16 | const result = renderer.getRenderOutput();
17 |
18 | expect(result.type).toEqual(XAxis);
19 | });
20 |
21 | it('should always have the id `xAxis`', () => {
22 | renderer.render();
23 | const result = renderer.getRenderOutput();
24 |
25 | expect(result.props).toHaveProperty('id', 'xAxis');
26 | });
27 |
28 | it('should NOT be a dynamic axis', () => {
29 | renderer.render();
30 | const result = renderer.getRenderOutput();
31 |
32 | expect(result.props).toHaveProperty('dynamicAxis', false);
33 | });
34 |
35 | it('passes other props through to ', () => {
36 | renderer.render();
37 | const result = renderer.getRenderOutput();
38 |
39 | expect(result.props).toHaveProperty('tickLength', 1337);
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/test/components/YAxis/YAxis.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import ShallowRenderer from 'react-test-renderer/shallow';
3 |
4 | import { YAxis } from 'react-jsx-highcharts';
5 | import MapYAxis from '../../../src/components/YAxis';
6 |
7 | describe('', () => {
8 | let renderer;
9 |
10 | beforeEach(() => {
11 | renderer = new ShallowRenderer();
12 | });
13 |
14 | it('renders a ', () => {
15 | renderer.render();
16 | const result = renderer.getRenderOutput();
17 |
18 | expect(result.type).toEqual(YAxis);
19 | });
20 |
21 | it('should always have the id `yAxis`', () => {
22 | renderer.render();
23 | const result = renderer.getRenderOutput();
24 |
25 | expect(result.props).toHaveProperty('id', 'yAxis');
26 | });
27 |
28 | it('should NOT be a dynamic axis', () => {
29 | renderer.render();
30 | const result = renderer.getRenderOutput();
31 |
32 | expect(result.props).toHaveProperty('dynamicAxis', false);
33 | });
34 |
35 | it('passes other props through to ', () => {
36 | renderer.render();
37 | const result = renderer.getRenderOutput();
38 |
39 | expect(result.props).toHaveProperty('tickLength', 1337);
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/test/test-helper.js:
--------------------------------------------------------------------------------
1 | // test setup here
2 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/test/test-utils.js:
--------------------------------------------------------------------------------
1 | export const uuidRegex =
2 | /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
3 |
4 | export const Highcharts = {
5 | mapChart: jest.fn(),
6 | addEvent: jest.fn(),
7 | removeEvent: jest.fn(),
8 | maps: {
9 | 'mock/map': { some: 'data' }
10 | },
11 | format: jest.fn()
12 | };
13 |
14 | export const createMockChart = () => ({
15 | addAxis: jest.fn(),
16 | addColorAxis: jest.fn(),
17 | addSeries: jest.fn(),
18 | get: jest.fn(),
19 | setSize: jest.fn(),
20 | update: jest.fn(),
21 | setTitle: jest.fn(),
22 | destroy: jest.fn(),
23 | showLoading: jest.fn(),
24 | hideLoading: jest.fn(),
25 | addCredits: jest.fn(),
26 | redraw: jest.fn(),
27 | setCaption: jest.fn(),
28 | options: { credits: {} }
29 | });
30 |
31 | export const createMockProvidedChart = ({ object, ...additional }) => {
32 | const chartStubs = createMockChart(additional);
33 |
34 | return {
35 | chartStubs: { ...chartStubs, object }
36 | };
37 | };
38 |
39 | export const createMockAxis = ({ ...additional }) => ({
40 | ...additional,
41 | remove: jest.fn(),
42 | addPlotBand: jest.fn(),
43 | removePlotBand: jest.fn(),
44 | addPlotLine: jest.fn(),
45 | removePlotLine: jest.fn(),
46 | getExtremes: jest.fn(),
47 | setExtremes: jest.fn(),
48 | update: jest.fn(),
49 | setTitle: jest.fn()
50 | });
51 |
52 | export const createMockProvidedAxis = ({ object, ...additional }) => {
53 | const axisStubs = createMockAxis(additional);
54 |
55 | return {
56 | axisStubs,
57 | getAxis: () => ({
58 | object,
59 | ...additional,
60 | ...axisStubs
61 | })
62 | };
63 | };
64 |
65 | export const createMockSeries = ({ ...additional }) => ({
66 | ...additional,
67 | remove: jest.fn(),
68 | setData: jest.fn(),
69 | setVisible: jest.fn(),
70 | update: jest.fn()
71 | });
72 |
73 | export const createMockProvidedSeries = ({ object, ...additional }) => {
74 | const seriesStubs = createMockSeries(additional);
75 |
76 | return {
77 | seriesStubs,
78 | getSeries: () => ({
79 | object,
80 | ...additional,
81 | ...seriesStubs
82 | })
83 | };
84 | };
85 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "node",
4 | "noImplicitAny": true,
5 | "target": "ES2020"
6 | },
7 | "include": ["./types/**/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/types/index.d.ts:
--------------------------------------------------------------------------------
1 | import type * as Highcharts from 'highcharts';
2 | import type { ReactElement, ReactNode } from 'react';
3 | import type {
4 | HighchartsChartProps,
5 | SeriesProps,
6 | AxisProps
7 | } from 'react-jsx-highcharts';
8 |
9 | export {
10 | Chart,
11 | ColorAxis,
12 | Credits,
13 | Debug,
14 | HighchartsProvider as HighmapsProvider,
15 | Loading,
16 | Legend,
17 | Series,
18 | Subtitle,
19 | Title,
20 | Tooltip,
21 | useHighcharts,
22 | useChart,
23 | useAxis,
24 | useSeries,
25 | withHighcharts as withHighmaps,
26 | withSeriesType
27 | } from 'react-jsx-highcharts';
28 |
29 | type HighchartsMapChartsProps = HighchartsChartProps & {
30 | map: Highcharts.GeoJSON;
31 | };
32 |
33 | export function HighchartsMapChart(
34 | props: HighchartsMapChartsProps
35 | ): ReactElement;
36 |
37 | // Series
38 | export function MapSeries(
39 | props: SeriesProps
40 | ): ReactElement;
41 |
42 | export function MapPointSeries(
43 | props: SeriesProps
44 | ): ReactElement;
45 |
46 | export function MapLineSeries(
47 | props: SeriesProps
48 | ): ReactElement;
49 |
50 | export function MapBubbleSeries(
51 | props: SeriesProps
52 | ): ReactElement;
53 |
54 | // map navigator
55 | type MapNavigatorProps = {
56 | children?: ReactNode;
57 | } & Partial;
58 |
59 | export function MapNavigation(props: MapNavigatorProps): ReactElement;
60 | export namespace MapNavigation {
61 | type ZoomButtonProps = { children?: ReactNode } & Omit<
62 | TButtonProps,
63 | 'text'
64 | >;
65 |
66 | export function ZoomIn(
67 | props: ZoomButtonProps
68 | ): ReactElement;
69 |
70 | export function ZoomOut(
71 | props: ZoomButtonProps
72 | ): ReactElement;
73 |
74 | type MapButtonProps = {
75 | children?: ReactNode;
76 | type: 'zoomIn' | 'zoomOut';
77 | } & Omit;
78 | export function Button(props: MapButtonProps): ReactElement;
79 | }
80 |
81 | // Axis components
82 | type MapAxisProps = {
83 | endOnTick?: boolean;
84 | visible?: boolean;
85 | minPadding?: number;
86 | maxPadding?: number;
87 | startOnTick?: boolean;
88 | reversed?: boolean;
89 | } & AxisProps;
90 |
91 | export function XAxis(
92 | props: MapAxisProps
93 | ): ReactElement;
94 | export function YAxis(
95 | props: MapAxisProps
96 | ): ReactElement;
97 |
--------------------------------------------------------------------------------
/packages/react-jsx-highmaps/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const path = require('path');
3 |
4 | const isProd = process.env.NODE_ENV === 'production';
5 |
6 | const webpackConfig = {
7 | mode: 'development',
8 |
9 | entry: path.resolve(__dirname, 'src'),
10 |
11 | output: {
12 | filename: isProd ? 'react-jsx-highmaps.min.js' : 'react-jsx-highmaps.js',
13 | path: path.resolve(__dirname, 'dist'),
14 | library: 'ReactHighcharts',
15 | libraryTarget: 'umd',
16 | // Prevents webpack from referencing `window` in the UMD build
17 | // Source: https://git.io/vppgU
18 | globalObject: "typeof self !== 'undefined' ? self : this"
19 | },
20 |
21 | externals: {
22 | react: {
23 | commonjs: 'react',
24 | commonjs2: 'react',
25 | amd: 'react',
26 | root: 'React'
27 | },
28 | 'react-dom': {
29 | commonjs: 'react-dom',
30 | commonjs2: 'react-dom',
31 | amd: 'react-dom',
32 | root: 'ReactDOM'
33 | },
34 | highcharts: {
35 | commonjs: 'highcharts',
36 | commonjs2: 'highcharts',
37 | amd: 'highcharts',
38 | root: 'Highcharts'
39 | }
40 | },
41 |
42 | module: {
43 | rules: [
44 | {
45 | test: /\.js$/,
46 | loader: 'babel-loader',
47 | exclude: /node_modules(\\|\/)(?!react-jsx-highcharts)/
48 | }
49 | ]
50 | }
51 | };
52 |
53 | if (isProd) {
54 | webpackConfig.mode = 'production';
55 | }
56 |
57 | module.exports = webpackConfig;
58 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/.babelrc:
--------------------------------------------------------------------------------
1 | { "extends": "../../babel.config.js" }
2 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/jest.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | // For a detailed explanation regarding each configuration property, visit:
3 | // https://jestjs.io/docs/en/configuration.html
4 |
5 | /** @type {import('@jest/types').Config.InitialOptions} */
6 | const config = {
7 | testEnvironment: 'jsdom',
8 | setupFilesAfterEnv: ['/test/test-helper.js'],
9 | testMatch: ['**/test/**/*.spec.js?(x)']
10 | };
11 |
12 | module.exports = config;
13 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-jsx-highstock",
3 | "version": "5.0.0",
4 | "description": "Highcharts (including Highstock) charts built using React components",
5 | "main": "dist/react-jsx-highstock.min.js",
6 | "module": "dist/es/index.js",
7 | "types": "types/index.d.ts",
8 | "sideEffects": false,
9 | "files": [
10 | "dist",
11 | "src",
12 | "types"
13 | ],
14 | "scripts": {
15 | "build": "cross-env NODE_ENV=development webpack",
16 | "build:prod": "npm run build:umd && npm run build:es",
17 | "build:umd": "cross-env NODE_ENV=production webpack",
18 | "build:es": "cross-env BABEL_ENV=es babel src --out-dir dist/es",
19 | "clean": "rimraf dist",
20 | "format": "prettier --write \"src/**/*.js\" \"test/**/*.js\" README.md",
21 | "lint": "eslint src",
22 | "test": "jest",
23 | "test:coverage": "jest --coverage",
24 | "test:types": "tsc --noEmit"
25 | },
26 | "author": "Will Hawker",
27 | "contributors": [
28 | {
29 | "name": "Alex Mayants",
30 | "url": "https://github.com/AlexMayants"
31 | },
32 | {
33 | "name": "mrawdon",
34 | "url": "https://github.com/mrawdon"
35 | },
36 | {
37 | "name": "Ercan Akyürek",
38 | "url": "https://github.com/geforcefan"
39 | },
40 | {
41 | "name": "anajavi",
42 | "url": "https://github.com/anajavi"
43 | }
44 | ],
45 | "license": "MIT",
46 | "repository": {
47 | "type": "git",
48 | "url": "https://github.com/whawker/react-jsx-highcharts.git"
49 | },
50 | "bugs": "https://github.com/whawker/react-jsx-highcharts/issues",
51 | "homepage": "https://github.com/whawker/react-jsx-highcharts",
52 | "keywords": [
53 | "react",
54 | "reactjs",
55 | "react-component",
56 | "highcharts",
57 | "highstock",
58 | "chart",
59 | "charts",
60 | "graphs",
61 | "visualization",
62 | "data"
63 | ],
64 | "dependencies": {
65 | "react-jsx-highcharts": "5.0.0"
66 | },
67 | "peerDependencies": {
68 | "highcharts": "^9.1.2 || ^10.0.0",
69 | "react": "^17.0.0 || ^18.0.0",
70 | "react-dom": "^17.0.0 || ^18.0.0"
71 | },
72 | "browserslist": [
73 | "chrome >= 81",
74 | "edge >= 81",
75 | "firefox >= 78",
76 | "ios >= 12",
77 | "safari >= 12"
78 | ]
79 | }
80 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/HighchartsStockChart/HighchartsStockChart.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { BaseChart, useHighcharts } from 'react-jsx-highcharts';
3 |
4 | const HighchartsStockChart = props => {
5 | const Highcharts = useHighcharts();
6 |
7 | return (
8 |
13 | );
14 | };
15 |
16 | export default HighchartsStockChart;
17 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/HighchartsStockChart/index.js:
--------------------------------------------------------------------------------
1 | import HighchartsStockChart from './HighchartsStockChart';
2 | export default HighchartsStockChart;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Navigator/Navigator.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useState, useEffect } from 'react';
3 | import {
4 | useModifiedProps,
5 | useChart,
6 | useHighcharts
7 | } from 'react-jsx-highcharts';
8 | import NavigatorXAxis from './NavigatorXAxis';
9 |
10 | const Navigator = ({ enabled = true, ...restProps }) => {
11 | const props = { enabled, ...restProps };
12 | const [rendered, setRendered] = useState(false);
13 | const chart = useChart();
14 | const Highcharts = useHighcharts();
15 |
16 | useEffect(() => {
17 | const { children, ...rest } = props;
18 | // Workaround from http://jsfiddle.net/x40me94t/2/
19 | const chartObj = chart.object;
20 | chartObj.options.navigator.enabled = true;
21 | // Initialise Navigator https://github.com/highcharts/highcharts/blob/dd730ab/js/parts/Navigator.js#L1837-L1844
22 | Highcharts.fireEvent(chartObj, 'beforeRender');
23 |
24 | updateNavigator(rest, chart);
25 |
26 | setRendered(true);
27 |
28 | return () => {
29 | try {
30 | updateNavigator({ enabled: false }, chart);
31 | } catch {
32 | // ignore as chart might have been already unmounted
33 | }
34 | };
35 | }, []);
36 |
37 | const modifiedProps = useModifiedProps(props);
38 |
39 | useEffect(() => {
40 | if (modifiedProps !== false) {
41 | updateNavigator(modifiedProps, chart);
42 | }
43 | });
44 |
45 | const { children } = props;
46 | if (!children || !rendered) return null;
47 |
48 | return {children};
49 | };
50 |
51 | const updateNavigator = (config, chart) => {
52 | chart.update({ navigator: config }, true);
53 | };
54 |
55 | export default Navigator;
56 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Navigator/NavigatorAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import {
3 | useRef,
4 | useEffect,
5 | Children,
6 | cloneElement,
7 | isValidElement
8 | } from 'react';
9 | import {
10 | useAxis,
11 | useModifiedProps,
12 | getNonEventHandlerProps
13 | } from 'react-jsx-highcharts';
14 |
15 | const NavigatorAxis = ({ children, axisId, ...restProps }) => {
16 | const axis = useAxis(axisId);
17 | const renderedRef = useRef(false);
18 |
19 | useEffect(() => {
20 | if (!axis) return;
21 |
22 | updateNavigatorAxis(getNonEventHandlerProps(restProps), axis);
23 | }, [axis]);
24 |
25 | const modifiedProps = useModifiedProps(restProps);
26 |
27 | useEffect(() => {
28 | if (!renderedRef.current) {
29 | // don't update on first render
30 | renderedRef.current = true;
31 | return;
32 | }
33 |
34 | if (!axis) return;
35 |
36 | if (modifiedProps !== false) {
37 | updateNavigatorAxis(modifiedProps, axis);
38 | }
39 | });
40 |
41 | if (!children) return null;
42 |
43 | const axisChildren = Children.map(children, child => {
44 | if (isValidElement(child) === false) return child;
45 | return cloneElement(child, { axisId });
46 | });
47 |
48 | return <>{axisChildren}>;
49 | };
50 | const updateNavigatorAxis = (config, axis) => {
51 | axis.update(config);
52 | };
53 |
54 | export default NavigatorAxis;
55 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Navigator/NavigatorSeries.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { useSeries } from 'react-jsx-highcharts';
3 |
4 | const NavigatorSeries = props => {
5 | const series = useSeries(props.seriesId);
6 |
7 | useEffect(() => {
8 | if (!series) return;
9 |
10 | updateNavigatorSeries(series, { showInNavigator: true });
11 | return () => {
12 | try {
13 | updateNavigatorSeries(series, { showInNavigator: false });
14 | } catch {
15 | // ignore as series might have been already unmounted
16 | }
17 | };
18 | }, [series]);
19 |
20 | return null;
21 | };
22 |
23 | const updateNavigatorSeries = (series, config) => {
24 | series.update(config);
25 | };
26 |
27 | export default NavigatorSeries;
28 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Navigator/NavigatorXAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import NavigatorAxis from './NavigatorAxis';
3 |
4 | const NavigatorXAxis = props => (
5 |
6 | );
7 |
8 | export default NavigatorXAxis;
9 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Navigator/NavigatorYAxis.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import NavigatorAxis from './NavigatorAxis';
3 |
4 | const NavigatorYAxis = props => (
5 |
6 | );
7 |
8 | export default NavigatorYAxis;
9 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Navigator/index.js:
--------------------------------------------------------------------------------
1 | import Navigator from './Navigator';
2 | import NavigatorSeries from './NavigatorSeries';
3 | import NavigatorXAxis from './NavigatorXAxis';
4 | import NavigatorYAxis from './NavigatorYAxis';
5 | const ChartNavigator = Navigator;
6 | ChartNavigator.Series = NavigatorSeries;
7 | ChartNavigator.XAxis = NavigatorXAxis;
8 | ChartNavigator.YAxis = NavigatorYAxis;
9 | export default ChartNavigator;
10 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/RangeSelector/RangeSelector.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useState, useEffect } from 'react';
3 | import {
4 | useHighcharts,
5 | useAxis,
6 | useChart,
7 | useModifiedProps
8 | } from 'react-jsx-highcharts';
9 |
10 | const RangeSelector = ({ enabled = true, children, ...restProps }) => {
11 | const props = { enabled, ...restProps };
12 | const [rendered, setRendered] = useState(false);
13 | const Highcharts = useHighcharts();
14 | const chart = useChart();
15 | const axis = useAxis('xAxis');
16 |
17 | useEffect(() => {
18 | if (!axis) return;
19 |
20 | // Workaround inferred from http://jsfiddle.net/x40me94t/2/
21 | const chartObj = chart.object;
22 | chartObj.options.rangeSelector.enabled = true;
23 | // Initialise RangeSelector (see https://github.com/highcharts/highcharts/blob/dd730ab/js/parts/RangeSelector.js#L1464-L1468)
24 | Highcharts.fireEvent(chartObj, 'afterGetContainer');
25 |
26 | const opts = getRangeSelectorConfig(props, Highcharts);
27 | updateRangeSelector(opts, chart);
28 |
29 | const renderRangeSelector = createRenderRangeSelector(chart, axis);
30 | const axisObj = axis.object;
31 | Highcharts.addEvent(axisObj, 'afterSetExtremes', renderRangeSelector);
32 |
33 | setRendered(true);
34 |
35 | return () => {
36 | const axisObj = axis.object;
37 | Highcharts.removeEvent(axisObj, 'afterSetExtremes', renderRangeSelector);
38 | try {
39 | updateRangeSelector({ enabled: false }, chart);
40 | } catch {
41 | // ignore as chart might have been already unmounted
42 | }
43 | };
44 | }, [axis]);
45 |
46 | const modifiedProps = useModifiedProps(props);
47 |
48 | useEffect(() => {
49 | if (!axis || !rendered) return;
50 |
51 | if (modifiedProps !== false) {
52 | updateRangeSelector(modifiedProps, chart);
53 | }
54 | });
55 |
56 | if (!children || !rendered) return null;
57 |
58 | return <>{children}>;
59 | };
60 |
61 | const getRangeSelectorConfig = (props, Highcharts) => {
62 | return {
63 | ...(Highcharts.defaultOptions && Highcharts.defaultOptions.rangeSelector),
64 | ...props,
65 | inputEnabled: false,
66 | buttons: []
67 | };
68 | };
69 |
70 | const updateRangeSelector = (config, chart) => {
71 | chart.update({ rangeSelector: config }, true);
72 | };
73 |
74 | const createRenderRangeSelector = (chart, axis) => {
75 | return () => {
76 | const chartObj = chart.object;
77 | const extremes = axis.getExtremes();
78 | // Fixes #40
79 | chartObj.rangeSelector.render.call(
80 | chartObj.rangeSelector,
81 | extremes.min,
82 | extremes.max
83 | );
84 | };
85 | };
86 |
87 | export default RangeSelector;
88 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/RangeSelector/RangeSelectorButton.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { getEventsConfig, useChart } from 'react-jsx-highcharts';
3 |
4 | const RangeSelectorButton = ({
5 | count = 1,
6 | offsetMin = 0,
7 | offsetMax = 0,
8 | ...restProps
9 | }) => {
10 | const props = { count, offsetMin, offsetMax, ...restProps };
11 |
12 | const chart = useChart();
13 |
14 | useEffect(() => {
15 | const button = getButtonIndex(props, chart);
16 | if (button > -1) return; // Button already present
17 |
18 | const {
19 | count,
20 | type,
21 | offsetMin,
22 | offsetMax,
23 | dataGrouping,
24 | children: text,
25 | ...rest
26 | } = props;
27 | const opts = {
28 | count,
29 | type,
30 | offsetMin,
31 | offsetMax,
32 | dataGrouping,
33 | text,
34 | events: getEventsConfig(rest)
35 | };
36 |
37 | addButton(opts, chart);
38 |
39 | return () => {
40 | try {
41 | removeButton(props, chart);
42 | } catch {
43 | // ignore as chart might have been already unmounted
44 | }
45 | };
46 | }, []);
47 |
48 | return null;
49 | };
50 |
51 | const getButtons = chart => {
52 | const chartObj = chart.object;
53 | if (chartObj && chartObj.options) {
54 | const { buttons = [] } = chartObj.options.rangeSelector;
55 | return buttons;
56 | }
57 |
58 | return [];
59 | };
60 |
61 | const getButtonIndex = (props, chart) => {
62 | const { count, type } = props;
63 | return getButtons(chart).findIndex(b => {
64 | return b.count === count && b.type === type;
65 | });
66 | };
67 |
68 | const addButton = (config, chart) => {
69 | // Add button to array
70 | const buttons = [...getButtons(chart), config];
71 | updateRangeSelectorButtons(buttons, chart);
72 | };
73 |
74 | const removeButton = (props, chart) => {
75 | const button = getButtonIndex(props);
76 | if (button === -1) return;
77 |
78 | // Remove button from array
79 | const buttons = [...getButtons()];
80 | buttons.splice(button, 1);
81 | updateRangeSelectorButtons(buttons, chart);
82 | };
83 |
84 | const updateRangeSelectorButtons = (config, chart) => {
85 | chart.update({
86 | rangeSelector: {
87 | buttons: config
88 | }
89 | });
90 | };
91 |
92 | export default RangeSelectorButton;
93 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/RangeSelector/RangeSelectorInput.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { useModifiedProps, useChart } from 'react-jsx-highcharts';
3 |
4 | const RangeSelectorInput = ({ enabled = true, ...restProps }) => {
5 | const chart = useChart();
6 |
7 | useEffect(() => {
8 | return () => {
9 | try {
10 | updateRangeSelectorInputs({ enabled: false }, chart);
11 | } catch {
12 | // ignore as chart might have been already unmounted
13 | }
14 | };
15 | }, []);
16 |
17 | const modifiedProps = useModifiedProps({ enabled, ...restProps });
18 |
19 | useEffect(() => {
20 | if (modifiedProps !== false) {
21 | updateRangeSelectorInputs(modifiedProps, chart);
22 | }
23 | });
24 |
25 | return null;
26 | };
27 |
28 | const upperFirst = str => {
29 | return str.charAt(0).toUpperCase() + str.slice(1);
30 | };
31 |
32 | const prefixPropsWithInput = config => {
33 | const prefixedConfig = {};
34 | Object.keys(config).forEach(key => {
35 | const newKey = key.indexOf('input') === 0 ? key : `input${upperFirst(key)}`;
36 | prefixedConfig[newKey] = config[key];
37 | });
38 |
39 | return prefixedConfig;
40 | };
41 |
42 | const updateRangeSelectorInputs = (config, chart) => {
43 | const inputProps = prefixPropsWithInput(config);
44 |
45 | chart.update({
46 | rangeSelector: {
47 | ...inputProps
48 | }
49 | });
50 | };
51 |
52 | export default RangeSelectorInput;
53 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/RangeSelector/index.js:
--------------------------------------------------------------------------------
1 | import RangeSelector from './RangeSelector';
2 | import RangeSelectorButton from './RangeSelectorButton';
3 | import RangeSelectorInput from './RangeSelectorInput';
4 | const ChartRangeSelector = RangeSelector;
5 | ChartRangeSelector.Button = RangeSelectorButton;
6 | ChartRangeSelector.Input = RangeSelectorInput;
7 | export default ChartRangeSelector;
8 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Scrollbar/Scrollbar.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { useEffect } from 'react';
3 | import { useModifiedProps, useChart } from 'react-jsx-highcharts';
4 |
5 | const Scrollbar = ({ children, enabled = true, ...restProps }) => {
6 | const chart = useChart();
7 |
8 | useEffect(() => {
9 | return () => {
10 | try {
11 | updateScrollbar({ enabled: false }, chart);
12 | } catch {
13 | // ignore as chart might have been already unmounted
14 | }
15 | };
16 | }, []);
17 |
18 | const modifiedProps = useModifiedProps({ enabled, ...restProps });
19 |
20 | useEffect(() => {
21 | if (modifiedProps !== false) {
22 | updateScrollbar(modifiedProps, chart);
23 | }
24 | });
25 |
26 | if (!children) return null;
27 |
28 | return <>{children}>;
29 | };
30 |
31 | const updateScrollbar = (config, chart) => {
32 | chart.update({ scrollbar: config }, true);
33 | };
34 |
35 | export default Scrollbar;
36 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/components/Scrollbar/index.js:
--------------------------------------------------------------------------------
1 | import Scrollbar from './Scrollbar';
2 | export default Scrollbar;
3 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/src/index.js:
--------------------------------------------------------------------------------
1 | import { withSeriesType } from 'react-jsx-highcharts';
2 | export * from 'react-jsx-highcharts';
3 |
4 | // Charts
5 | export { default as HighchartsStockChart } from './components/HighchartsStockChart';
6 |
7 | // Graph parts
8 | export { default as Navigator } from './components/Navigator';
9 | export { default as RangeSelector } from './components/RangeSelector';
10 | export { default as Scrollbar } from './components/Scrollbar';
11 |
12 | // Series
13 | export const CandlestickSeries = withSeriesType('Candlestick');
14 | export const FlagsSeries = withSeriesType('Flags');
15 | export const OHLCSeries = withSeriesType('OHLC');
16 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | "jest": true
5 | },
6 | "rules": {
7 | "no-unused-vars": ["warn"],
8 | "react-perf/jsx-no-new-function-as-prop": "off",
9 | "react-perf/jsx-no-new-object-as-prop": "off",
10 | "react-perf/jsx-no-new-array-as-prop": "off",
11 | "react/display-name": "off"
12 | },
13 | "globals": {
14 | "mount": true,
15 | "shallow": true,
16 | "render": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/components/HighchartsStockChart/HighchartsStockChart.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | jest.mock('react-jsx-highcharts', () => ({
5 | ...jest.requireActual('react-jsx-highcharts'),
6 | useHighcharts: jest.fn()
7 | }));
8 |
9 | import { useHighcharts } from 'react-jsx-highcharts';
10 | import { Highcharts, createMockChart } from '../../test-utils';
11 | import HighchartsStockChart from '../../../src/components/HighchartsStockChart/HighchartsStockChart';
12 |
13 | describe('', () => {
14 | beforeEach(() => {
15 | const chart = createMockChart();
16 | Highcharts.stockChart.mockReturnValue(chart);
17 |
18 | useHighcharts.mockImplementation(() => Highcharts);
19 | });
20 |
21 | it('creates a chart', () => {
22 | render();
23 |
24 | expect(Highcharts.stockChart).toHaveBeenCalled();
25 | });
26 |
27 | it('creates a chart with the correct chart type', () => {
28 | render();
29 |
30 | expect(Highcharts.stockChart).toHaveBeenCalledWith(
31 | expect.anything(),
32 | expect.objectContaining({
33 | chartType: 'stockChart'
34 | })
35 | );
36 | });
37 |
38 | it('passes other props through to the chart', () => {
39 | render();
40 |
41 | expect(Highcharts.stockChart).toHaveBeenCalledWith(
42 | expect.anything(),
43 | expect.objectContaining({ plotOptions: { c: 'd' } })
44 | );
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/components/Navigator/Navigator.integration.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import Highstock from 'highcharts/highstock';
5 | import addAccessibility from 'highcharts/modules/accessibility';
6 |
7 | import {
8 | Chart,
9 | Debug,
10 | XAxis,
11 | YAxis,
12 | LineSeries,
13 | HighchartsProvider
14 | } from 'react-jsx-highcharts';
15 | import { HighchartsStockChart, Navigator } from '../../../src';
16 |
17 | addAccessibility(Highstock);
18 |
19 | describe(' integration', () => {
20 | describe('when mounted', () => {
21 | it('creates navigator on chart', () => {
22 | const data = [1, 2, 3, 4, 5];
23 | const Component = () => {
24 | return (
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | );
37 | };
38 | render();
39 | const chart = window.chart;
40 |
41 | expect(chart.options.navigator.enabled).toEqual(true);
42 | });
43 |
44 | it('passed additional props to navigator on chart', () => {
45 | const data = [1, 2, 3, 4, 5];
46 | const Component = () => {
47 | return (
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | );
60 | };
61 | render();
62 | const chart = window.chart;
63 |
64 | expect(chart.options.navigator.height).toEqual(100);
65 | });
66 | });
67 |
68 | describe('when updated', () => {
69 | it('changes height of the chart', () => {
70 | const data = [1, 2, 3, 4, 5];
71 | const Component = props => {
72 | return (
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | );
85 | };
86 |
87 | const wrapper = render();
88 | wrapper.rerender();
89 | const chart = window.chart;
90 |
91 | expect(chart.options.navigator.height).toEqual(110);
92 | });
93 | });
94 | });
95 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/components/Navigator/Navigator.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | jest.mock('react-jsx-highcharts', () => ({
5 | ...jest.requireActual('react-jsx-highcharts'),
6 | useChart: jest.fn(),
7 | useHighcharts: jest.fn()
8 | }));
9 |
10 | import { useChart, useHighcharts } from 'react-jsx-highcharts';
11 | import Navigator from '../../../src/components/Navigator/Navigator';
12 | import { Highcharts, createMockProvidedChart } from '../../test-utils';
13 |
14 | describe('', () => {
15 | let testContext;
16 |
17 | beforeEach(() => {
18 | testContext = {};
19 | testContext.object = {
20 | options: { navigator: { enabled: false } }
21 | };
22 | const { chartStubs } = createMockProvidedChart({
23 | object: testContext.object
24 | });
25 | testContext.chartStubs = chartStubs;
26 |
27 | useChart.mockImplementation(() => chartStubs);
28 | useHighcharts.mockImplementation(() => Highcharts);
29 | });
30 |
31 | afterEach(() => {
32 | jest.resetAllMocks();
33 | });
34 |
35 | describe('when mounted', () => {
36 | it('enables the Navigator', () => {
37 | render();
38 | expect(testContext.object.options.navigator.enabled).toEqual(true);
39 | });
40 |
41 | it('fires the `beforeRender` event to so Highcharts creates a Navigator', () => {
42 | render();
43 | expect(Highcharts.fireEvent).toHaveBeenCalledWith(
44 | testContext.object,
45 | 'beforeRender'
46 | );
47 | });
48 |
49 | it('updates the chart with the passed props', () => {
50 | render();
51 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
52 | {
53 | navigator: {
54 | enabled: true,
55 | height: 100,
56 | maskFill: 'rgba(1,2,3,0.45)'
57 | }
58 | },
59 | true
60 | );
61 | });
62 | });
63 |
64 | describe('update', () => {
65 | it('should use the update method when props change', () => {
66 | const wrapper = render();
67 | wrapper.rerender();
68 |
69 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
70 | {
71 | navigator: {
72 | maskInside: false
73 | }
74 | },
75 | expect.any(Boolean)
76 | );
77 | });
78 | });
79 |
80 | describe('when unmounted', () => {
81 | it('should disable the Navigator', () => {
82 | const wrapper = render();
83 | wrapper.unmount();
84 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
85 | {
86 | navigator: {
87 | enabled: false
88 | }
89 | },
90 | expect.any(Boolean)
91 | );
92 | });
93 | });
94 | });
95 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/components/Navigator/NavigatorXAxis.integration.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import Highstock from 'highcharts/highstock';
5 | import addAccessibility from 'highcharts/modules/accessibility';
6 |
7 | import {
8 | Chart,
9 | Debug,
10 | XAxis,
11 | YAxis,
12 | LineSeries,
13 | HighchartsProvider
14 | } from 'react-jsx-highcharts';
15 | import { HighchartsStockChart, Navigator } from '../../../src';
16 |
17 | addAccessibility(Highstock);
18 |
19 | describe(' integration', () => {
20 | describe('when mounted', () => {
21 | it('passes additional props to navigators xAxis', () => {
22 | const data = [1, 2, 3, 4, 5];
23 | const labels = { x: 0, y: 12 };
24 | const Component = () => {
25 | return (
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | };
41 | render();
42 | const chart = window.chart;
43 | const navigatorxaxis = chart.get('navigator-x-axis');
44 |
45 | expect(navigatorxaxis.options.labels).toEqual(
46 | expect.objectContaining(labels)
47 | );
48 | });
49 | });
50 |
51 | describe('when updated', () => {
52 | it('changes the navigator labels', () => {
53 | const data = [1, 2, 3, 4, 5];
54 | const labels = { x: 0, y: 12 };
55 | const Component = props => {
56 | return (
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | );
71 | };
72 |
73 | const wrapper = render();
74 | wrapper.rerender();
75 | const chart = window.chart;
76 | const navigatorxaxis = chart.get('navigator-x-axis');
77 |
78 | expect(navigatorxaxis.options.labels).toEqual(
79 | expect.objectContaining(labels)
80 | );
81 | });
82 | });
83 | });
84 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/components/RangeSelector/RangeSelector.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import {
5 | Highcharts,
6 | createMockProvidedChart,
7 | createMockProvidedAxis
8 | } from '../../test-utils';
9 | jest.mock('react-jsx-highcharts', () => ({
10 | ...jest.requireActual('react-jsx-highcharts'),
11 | useChart: jest.fn(),
12 | useHighcharts: jest.fn(),
13 | useAxis: jest.fn()
14 | }));
15 | import { useAxis, useChart, useHighcharts } from 'react-jsx-highcharts';
16 |
17 | import RangeSelector from '../../../src/components/RangeSelector/RangeSelector';
18 |
19 | describe('', () => {
20 | let testContext;
21 |
22 | beforeEach(() => {
23 | testContext = {};
24 | testContext.object = {
25 | options: { rangeSelector: { enabled: false } }
26 | };
27 | const { chartStubs } = createMockProvidedChart({
28 | object: testContext.object
29 | });
30 | testContext.chartStubs = chartStubs;
31 | testContext.chartStubs.update.mockReset();
32 | testContext.axisObject = {};
33 | const { axisStubs } = createMockProvidedAxis({
34 | object: testContext.axisObject
35 | });
36 | testContext.axisStubs = axisStubs;
37 |
38 | useAxis.mockImplementation(id => {
39 | axisStubs.id = id;
40 | return axisStubs;
41 | });
42 |
43 | useChart.mockImplementation(() => chartStubs);
44 | useHighcharts.mockImplementation(() => Highcharts);
45 | });
46 |
47 | describe('when mounted', () => {
48 | it('enables the RangeSelector', () => {
49 | render();
50 |
51 | expect(testContext.object.options.rangeSelector.enabled).toEqual(true);
52 | });
53 |
54 | it('fires the initialization event to so Highcharts creates a RangeSelector', () => {
55 | render();
56 |
57 | expect(Highcharts.fireEvent).toHaveBeenCalledWith(
58 | testContext.object,
59 | 'afterGetContainer'
60 | );
61 | });
62 |
63 | it('updates the chart with the passed props', () => {
64 | render();
65 |
66 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
67 | {
68 | rangeSelector: {
69 | enabled: true,
70 | inputEnabled: false,
71 | height: 100,
72 | buttonSpacing: 2,
73 | buttons: []
74 | }
75 | },
76 | expect.any(Boolean)
77 | );
78 | });
79 |
80 | it('updates the chart once', () => {
81 | render();
82 |
83 | expect(testContext.chartStubs.update).toHaveBeenCalledTimes(1);
84 | });
85 | });
86 |
87 | describe('update', () => {
88 | it('should use the update method when props change', () => {
89 | const wrapper = render();
90 | testContext.chartStubs.update.mockClear();
91 | wrapper.rerender();
92 |
93 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
94 | {
95 | rangeSelector: {
96 | selected: 2
97 | }
98 | },
99 | expect.any(Boolean)
100 | );
101 | });
102 | });
103 |
104 | describe('when unmounted', () => {
105 | it('should disable the RangeSelector', () => {
106 | const wrapper = render();
107 | testContext.chartStubs.update.mockClear();
108 | wrapper.unmount();
109 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
110 | {
111 | rangeSelector: {
112 | enabled: false
113 | }
114 | },
115 | expect.any(Boolean)
116 | );
117 | });
118 | });
119 | });
120 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/components/RangeSelector/RangeSelectorInput.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import {
5 | Highcharts,
6 | createMockProvidedChart,
7 | createMockProvidedAxis
8 | } from '../../test-utils';
9 | jest.mock('react-jsx-highcharts', () => ({
10 | ...jest.requireActual('react-jsx-highcharts'),
11 | useChart: jest.fn(),
12 | useHighcharts: jest.fn(),
13 | useAxis: jest.fn()
14 | }));
15 | import { useAxis, useChart, useHighcharts } from 'react-jsx-highcharts';
16 |
17 | import RangeSelector from '../../../src/components/RangeSelector/RangeSelector';
18 | import RangeSelectorInput from '../../../src/components/RangeSelector/RangeSelectorInput';
19 |
20 | describe('', () => {
21 | let testContext;
22 |
23 | beforeEach(() => {
24 | testContext = {};
25 | testContext.object = {
26 | options: { rangeSelector: { enabled: false } }
27 | };
28 | const { chartStubs } = createMockProvidedChart({
29 | object: testContext.object
30 | });
31 | testContext.chartStubs = chartStubs;
32 | testContext.chartStubs.update.mockReset();
33 | testContext.axisObject = {};
34 | const { axisStubs } = createMockProvidedAxis({
35 | object: testContext.axisObject
36 | });
37 | testContext.axisStubs = axisStubs;
38 |
39 | useAxis.mockImplementation(id => {
40 | axisStubs.id = id;
41 | return axisStubs;
42 | });
43 |
44 | useChart.mockImplementation(() => chartStubs);
45 | useHighcharts.mockImplementation(() => Highcharts);
46 | });
47 |
48 | describe('when mounted', () => {
49 | it('sets the rangeselector input', () => {
50 | render(
51 |
52 |
53 |
54 | );
55 |
56 | expect(testContext.chartStubs.update).toHaveBeenCalledWith({
57 | rangeSelector: {
58 | inputBoxBorderColor: '#ffffff',
59 | inputEnabled: true
60 | }
61 | });
62 | });
63 | });
64 | });
65 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/components/Scrollbar/Scrollbar.spec.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from '@testing-library/react';
3 |
4 | import { createMockProvidedChart } from '../../test-utils';
5 |
6 | jest.mock('react-jsx-highcharts', () => ({
7 | ...jest.requireActual('react-jsx-highcharts'),
8 | useChart: jest.fn()
9 | }));
10 |
11 | import { useChart } from 'react-jsx-highcharts';
12 | import Scrollbar from '../../../src/components/Scrollbar/Scrollbar';
13 |
14 | describe('', () => {
15 | let testContext;
16 |
17 | beforeEach(() => {
18 | testContext = {};
19 | const { chartStubs } = createMockProvidedChart({
20 | object: testContext.object
21 | });
22 | testContext.chartStubs = chartStubs;
23 | useChart.mockImplementation(() => chartStubs);
24 | });
25 |
26 | describe('when mounted', () => {
27 | it('add scrollbar using the Highcharts update method', () => {
28 | render();
29 |
30 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
31 | {
32 | scrollbar: {
33 | enabled: true
34 | }
35 | },
36 | true
37 | );
38 | });
39 |
40 | it('updates the scrollbar with the passed props', () => {
41 | render();
42 |
43 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
44 | {
45 | scrollbar: {
46 | enabled: true,
47 | barBackgroundColor: 'red',
48 | height: 20
49 | }
50 | },
51 | true
52 | );
53 | });
54 | });
55 |
56 | describe('update', () => {
57 | it('should use the update method when props change', () => {
58 | const wrapper = render();
59 | testContext.chartStubs.update.mockClear();
60 | wrapper.rerender();
61 |
62 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
63 | {
64 | scrollbar: {
65 | height: 12345
66 | }
67 | },
68 | true
69 | );
70 | });
71 | });
72 |
73 | describe('when unmounted', () => {
74 | it('should disable the Scrollbar', () => {
75 | const wrapper = render();
76 | testContext.chartStubs.update.mockClear();
77 | wrapper.unmount();
78 | expect(testContext.chartStubs.update).toHaveBeenCalledWith(
79 | {
80 | scrollbar: {
81 | enabled: false
82 | }
83 | },
84 | true
85 | );
86 | });
87 | });
88 | });
89 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/test-helper.js:
--------------------------------------------------------------------------------
1 | const nodeCrypto = require('crypto');
2 | window.crypto = {
3 | getRandomValues: function (buffer) {
4 | return nodeCrypto.randomFillSync(buffer);
5 | }
6 | };
7 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/test/test-utils.js:
--------------------------------------------------------------------------------
1 | export const Highcharts = {
2 | stockChart: jest.fn(),
3 | addEvent: jest.fn(),
4 | removeEvent: jest.fn(),
5 | fireEvent: jest.fn()
6 | };
7 |
8 | export const createMockChart = ({ ...additional } = {}) => ({
9 | ...additional,
10 | addAxis: jest.fn(),
11 | addColorAxis: jest.fn(),
12 | addSeries: jest.fn(),
13 | get: jest.fn(),
14 | setSize: jest.fn(),
15 | update: jest.fn(),
16 | setTitle: jest.fn(),
17 | destroy: jest.fn(),
18 | showLoading: jest.fn(),
19 | hideLoading: jest.fn(),
20 | addCredits: jest.fn(),
21 | redraw: jest.fn(),
22 | setCaption: jest.fn()
23 | });
24 |
25 | export const createMockProvidedChart = ({ object, ...additional }) => {
26 | const chartStubs = createMockChart(additional);
27 |
28 | return {
29 | chartStubs: { ...chartStubs, object }
30 | };
31 | };
32 |
33 | export const createMockAxis = ({ ...additional } = {}) => ({
34 | ...additional,
35 | remove: jest.fn(),
36 | addPlotBand: jest.fn(),
37 | removePlotBand: jest.fn(),
38 | addPlotLine: jest.fn(),
39 | removePlotLine: jest.fn(),
40 | getExtremes: jest.fn(),
41 | setExtremes: jest.fn(),
42 | update: jest.fn(),
43 | setTitle: jest.fn()
44 | });
45 |
46 | export const createMockProvidedAxis = ({ object, ...additional }) => {
47 | const axisStubs = createMockAxis(additional);
48 |
49 | return {
50 | axisStubs,
51 | getAxis: () => ({
52 | object,
53 | ...additional,
54 | ...axisStubs
55 | })
56 | };
57 | };
58 |
59 | export const createMockSeries = ({ ...additional } = {}) => ({
60 | ...additional,
61 | remove: jest.fn(),
62 | setData: jest.fn(),
63 | setVisible: jest.fn(),
64 | update: jest.fn()
65 | });
66 |
67 | export const createMockProvidedSeries = ({ object, ...additional }) => {
68 | const seriesStubs = createMockSeries(additional);
69 |
70 | return {
71 | seriesStubs,
72 | getSeries: () => ({
73 | object,
74 | ...additional,
75 | ...seriesStubs
76 | })
77 | };
78 | };
79 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "node",
4 | "noImplicitAny": true,
5 | "target": "ES2020"
6 | },
7 | "include": ["./types/**/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/types/index.d.ts:
--------------------------------------------------------------------------------
1 | import type * as Highcharts from 'highcharts';
2 | import type { ReactElement, ReactNode } from 'react';
3 | import { HighchartsChartProps, SeriesProps } from 'react-jsx-highcharts';
4 |
5 | export * from 'react-jsx-highcharts';
6 |
7 | export function HighchartsStockChart(props: HighchartsChartProps): ReactElement;
8 |
9 | // Navigator
10 | type NavigatorProps = {
11 | children?: ReactNode;
12 | } & Partial;
13 | export function Navigator(props: NavigatorProps): ReactElement;
14 | export namespace Navigator {
15 | type NavigatorSeriesProps = {
16 | seriesId: string
17 | }
18 | export function Series(props: NavigatorSeriesProps): ReactElement;
19 |
20 | type NavigatorXAxisProps = {
21 | children?: ReactNode
22 | } & Partial;
23 | export function XAxis(props: NavigatorXAxisProps): ReactElement;
24 |
25 | type NavigatorYAxisProps = {
26 | children?: ReactNode
27 | } & Partial;
28 | export function YAxis(props: NavigatorYAxisProps): ReactElement;
29 | }
30 |
31 | // RangeSelector
32 | type RangeSelectorProps = {
33 | children?: ReactNode;
34 | } & Partial;
35 | export function RangeSelector(
36 | props: RangeSelectorProps
37 | ): ReactElement;
38 | export namespace RangeSelector {
39 | type RangeSelectorButtonProps = {
40 | children?: ReactNode;
41 | } & Partial>;
42 | export function Button(props: RangeSelectorButtonProps): ReactElement;
43 |
44 | type RangeSelectorInputProps = {
45 | boxBorderColor?: Highcharts.ColorString;
46 | boxHeight?: number;
47 | boxWidth?: (number|undefined);
48 | dateFormat?: string;
49 | dateParser?: Highcharts.RangeSelectorParseCallbackFunction;
50 | editDateFormat?: string;
51 | enabled?: boolean;
52 | position?: Highcharts.RangeSelectorInputPositionOptions;
53 | spacing?: number;
54 | style?: Highcharts.CSSObject;
55 | }
56 | export function Input(props: RangeSelectorInputProps): ReactElement;
57 | }
58 |
59 | // Scrollbar
60 | export function Scrollbar(props: Highcharts.ScrollbarOptions): ReactElement;
61 |
62 | // Series
63 | export function CandlestickSeries(
64 | props: SeriesProps
65 | ): ReactElement;
66 | export function FlagsSeries(
67 | props: SeriesProps
68 | ): ReactElement;
69 | export function OHLCSeries(
70 | props: SeriesProps
71 | ): ReactElement;
72 |
--------------------------------------------------------------------------------
/packages/react-jsx-highstock/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | const path = require('path');
3 |
4 | const isProd = process.env.NODE_ENV === 'production';
5 |
6 | const webpackConfig = {
7 | mode: 'development',
8 |
9 | entry: path.resolve(__dirname, 'src'),
10 |
11 | output: {
12 | filename: isProd ? 'react-jsx-highstock.min.js' : 'react-jsx-highstock.js',
13 | path: path.resolve(__dirname, 'dist'),
14 | library: 'ReactHighcharts',
15 | libraryTarget: 'umd',
16 | // Prevents webpack from referencing `window` in the UMD build
17 | // Source: https://git.io/vppgU
18 | globalObject: "typeof self !== 'undefined' ? self : this"
19 | },
20 |
21 | externals: {
22 | react: {
23 | commonjs: 'react',
24 | commonjs2: 'react',
25 | amd: 'react',
26 | root: 'React'
27 | },
28 | 'react-dom': {
29 | commonjs: 'react-dom',
30 | commonjs2: 'react-dom',
31 | amd: 'react-dom',
32 | root: 'ReactDOM'
33 | },
34 | highcharts: {
35 | commonjs: 'highcharts',
36 | commonjs2: 'highcharts',
37 | amd: 'highcharts',
38 | root: 'Highcharts'
39 | }
40 | },
41 |
42 | module: {
43 | rules: [
44 | {
45 | test: /\.js$/,
46 | loader: 'babel-loader',
47 | exclude: /node_modules(\\|\/)(?!react-jsx-highcharts)/
48 | }
49 | ]
50 | }
51 | };
52 |
53 | if (isProd) {
54 | webpackConfig.mode = 'production';
55 | }
56 |
57 | module.exports = webpackConfig;
58 |
--------------------------------------------------------------------------------