├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README-v2.2.md ├── README.md ├── babel.config.js ├── demo ├── .buckconfig ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .watchmanconfig ├── App.tsx ├── android │ ├── .project │ ├── .settings │ │ └── org.eclipse.buildship.core.prefs │ ├── app │ │ ├── .classpath │ │ ├── .project │ │ ├── .settings │ │ │ └── org.eclipse.buildship.core.prefs │ │ ├── _BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── linechartdemo │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── LineChartDemo-tvOS │ │ └── Info.plist │ ├── LineChartDemo-tvOSTests │ │ └── Info.plist │ ├── LineChartDemo.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── LineChartDemo-tvOS.xcscheme │ │ │ └── LineChartDemo.xcscheme │ ├── LineChartDemo.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── LineChartDemo │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── main.m │ ├── LineChartDemoTests │ │ ├── Info.plist │ │ └── LineChartDemoTests.m │ ├── Podfile │ └── Podfile.lock ├── metro.config.js ├── package.json ├── tsconfig.json └── yarn.lock ├── deploy_docs.sh ├── docusaurus ├── .gitignore ├── README.md ├── babel.config.js ├── blog │ ├── 2020-08-17-welcome.md │ └── 2020-10-1-v5.md ├── docs │ ├── area.md │ ├── chart.md │ ├── gettingstarted.md │ ├── horizontalaxis.md │ ├── line.md │ ├── screenshots.md │ ├── screenshots │ │ └── home.png │ ├── tooltip.md │ ├── types.md │ └── verticalaxis.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.js │ │ └── styles.module.css ├── static │ ├── .nojekyll │ └── img │ │ ├── Scrollable.gif │ │ ├── Tooltip.gif │ │ ├── area │ │ ├── example1.png │ │ └── example2.png │ │ ├── box.svg │ │ ├── chart │ │ └── example.png │ │ ├── favicon.ico │ │ ├── gettingstarted │ │ └── example.png │ │ ├── home.png │ │ ├── horizontalaxis │ │ ├── example1.png │ │ ├── example2.png │ │ └── example3.png │ │ ├── line │ │ ├── example1.png │ │ ├── example2.png │ │ └── example3.png │ │ ├── logo.svg │ │ ├── screenshots │ │ ├── example1.png │ │ ├── example2.png │ │ ├── example3.png │ │ ├── example4.png │ │ ├── example5.png │ │ ├── example6.png │ │ └── example7.png │ │ ├── smooth.png │ │ ├── smoothing.png │ │ ├── source.png │ │ ├── tooltip.png │ │ ├── typescript.svg │ │ └── verticalaxis │ │ ├── example1.png │ │ ├── example2.png │ │ └── example3.png └── yarn.lock ├── package.json ├── src ├── .watchmanconfig ├── Area.tsx ├── Axis.utils.spec.ts ├── Axis.utils.ts ├── Chart.tsx ├── Chart.utils.tsx ├── ChartContext.ts ├── HorizontalAxis.tsx ├── Line.tsx ├── Line.utils.ts ├── Tooltip.tsx ├── VerticalAxis.tsx ├── index.ts ├── types.ts ├── untypedModules.d.ts ├── useComponentDimensions.ts ├── utils.spec.ts └── utils.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | example/node_modules 9 | exampleapp/node_modules 10 | exampleapp/android/Build 11 | exampleapp/ios/build 12 | 13 | # OSX 14 | # 15 | .DS_Store 16 | 17 | # Xcode 18 | # 19 | exampleapp/build/ 20 | exampleapp/*.pbxuser 21 | exampleapp/!default.pbxuser 22 | exampleapp/*.mode1v3 23 | exampleapp/!default.mode1v3 24 | exampleapp/*.mode2v3 25 | exampleapp/!default.mode2v3 26 | exampleapp/*.perspectivev3 27 | exampleapp/!default.perspectivev3 28 | exampleapp/xcuserdata 29 | exampleapp/*.xccheckout 30 | exampleapp/*.moved-aside 31 | exampleapp/DerivedData 32 | exampleapp/*.hmap 33 | exampleapp/*.ipa 34 | exampleapp/*.xcuserstate 35 | exampleapp/project.xcworkspace 36 | 37 | # Android/IntelliJ 38 | # 39 | exampleapp/build/ 40 | exampleapp/.idea 41 | exampleapp/.gradle 42 | exampleapp/local.properties 43 | exampleapp/*.iml 44 | 45 | # node.js 46 | # 47 | exampleapp/node_modules/ 48 | exampleapp/npm-debug.log 49 | exampleapp/yarn-error.log 50 | 51 | # BUCK 52 | exampleapp/buck-out/ 53 | exampleapp/\.buckd/ 54 | exampleapp/*.keystore 55 | 56 | # fastlane 57 | # 58 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 59 | # screenshots whenever they are needed. 60 | # For more information about the recommended setup visit: 61 | # https://docs.fastlane.tools/best-practices/source-control/ 62 | 63 | exampleapp/*/fastlane/report.xml 64 | exampleapp/*/fastlane/Preview.html 65 | exampleapp/*/fastlane/screenshots 66 | 67 | lib/ 68 | 69 | # Bundle artifact 70 | exampleapp/*.jsbundle 71 | 72 | .expo 73 | 74 | .docz 75 | 76 | # Runtime data 77 | pids 78 | *.pid 79 | *.seed 80 | *.pid.lock 81 | 82 | # Directory for instrumented libs generated by jscoverage/JSCover 83 | lib-cov 84 | 85 | # Coverage directory used by tools like istanbul 86 | coverage 87 | 88 | # nyc test coverage 89 | .nyc_output 90 | 91 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 92 | .grunt 93 | 94 | # Bower dependency directory (https://bower.io/) 95 | bower_components 96 | 97 | # node-waf configuration 98 | .lock-wscript 99 | 100 | # Compiled binary addons (http://nodejs.org/api/addons.html) 101 | build/Release 102 | 103 | # Dependency directories 104 | node_modules/ 105 | jspm_packages/ 106 | 107 | # Typescript v1 declaration files 108 | typings/ 109 | 110 | # Optional npm cache directory 111 | .npm 112 | 113 | # Optional eslint cache 114 | .eslintcache 115 | 116 | # Optional REPL history 117 | .node_repl_history 118 | 119 | # Output of 'npm pack' 120 | *.tgz 121 | 122 | # Yarn Integrity file 123 | .yarn-integrity 124 | 125 | # dotenv environment variables file 126 | .env 127 | 128 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | demo 2 | src 3 | .docz 4 | deploy_docz.sh 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.md -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 160, 3 | "singleQuote": true, 4 | "semi": false 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Xander Deseyn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-v2.2.md: -------------------------------------------------------------------------------- 1 | # react-native-responsive-linechart 2 | 3 | 4 | 5 | ## Breaking changes in v2 6 | 7 | Tooltip and dataPoint (previously valuePoint) config is changed, check the default config for the correct keys. 8 | 9 | ## Installation 10 | 11 | ```js 12 | npm install react-native-responsive-linechart 13 | ``` 14 | 15 | ```js 16 | import LineChart from "react-native-responsive-linechart"; 17 | ``` 18 | 19 | No need to set an explicit width and height! Percentages or `flex` work just fine. 20 | 21 | ## Quick example 22 | 23 | 24 | 25 | ```jsx 26 | ; 27 | 28 | const data = [-10, -15, 40, 19, 32, 15, 52, 55, 20, 60, 78, 42, 56]; 29 | const config = { 30 | line: { 31 | visible: true, 32 | strokeWidth: 1, 33 | strokeColor: "#54a0ff" 34 | }, 35 | area: { 36 | visible: false 37 | }, 38 | tooltip: { 39 | visible: true, 40 | labelFontSize: 10 41 | }, 42 | grid: { 43 | stepSize: 10000 44 | }, 45 | yAxis: { 46 | labelColor: "#54a0ff" 47 | }, 48 | insetY: 10, 49 | insetX: 10 50 | }; 51 | ``` 52 | 53 | ## Reference 54 | 55 | ### LineChart 56 | 57 | | Property | Type | Description | Example | 58 | | -------- | ------ | ------------------------------ | --------------------- | 59 | | data | array | Your numeric data | [10, 22, 13, 15, 25] | 60 | | xLabels | array | Optional labels for the X axis | ['jan', 'feb', 'mar'] | 61 | | config | object | Chart configuration object | See next section | 62 | 63 | ### Default Config 64 | 65 | ```js 66 | const defaultConfig = { 67 | grid: { 68 | visible: true, 69 | backgroundColor: "#fff", 70 | strokeWidth: 1, 71 | strokeColor: "#ededed", 72 | stepSize: 15 73 | }, 74 | line: { 75 | visible: true, 76 | strokeWidth: 1, 77 | strokeColor: "#333" 78 | }, 79 | area: { 80 | visible: true, 81 | gradientFrom: "#be2ddd", 82 | gradientFromOpacity: 1, 83 | gradientTo: "#e056fd", 84 | gradientToOpacity: 0.4 85 | }, 86 | yAxis: { 87 | visible: true, 88 | labelFontSize: 12, 89 | labelColor: "#777", 90 | labelFormatter: v => String(v) 91 | }, 92 | xAxis: { 93 | visible: false, 94 | labelFontSize: 12, 95 | labelColor: "#777" 96 | }, 97 | tooltip: { 98 | visible: false, 99 | labelFormatter: v => v.toFixed(2), 100 | lineColor: "#777", 101 | lineWidth: 1, 102 | circleColor: "#fff", 103 | circleBorderColor: "#fff", 104 | circleBorderWidth: 1, 105 | boxColor: "#fff", 106 | boxBorderWidth: 1, 107 | boxBorderColor: "#777", 108 | boxBorderRadius: 5, 109 | boxPaddingY: 0, 110 | boxPaddingX: 0, 111 | labelColor: "black", 112 | labelFontSize: 10 113 | }, 114 | dataPoint: { 115 | visible: false, 116 | color: "#777", 117 | radius: 5, 118 | label: { 119 | visible: false, 120 | labelFontSize: 12, 121 | labelColor: "#777", 122 | labelFormatter: v => String(v), 123 | marginBottom: 25 124 | } 125 | }, 126 | insetY: 0, 127 | insetX: 0, 128 | interpolation: "none", 129 | backgroundColor: "#fff", 130 | backgroundOpacity: 1 131 | }; 132 | ``` 133 | 134 | ## More examples 135 | 136 | 137 | 138 | ```jsx 139 | const data = [-10, -15, 40, 60, 78, 42, 56]; 140 | const labels = ["jan", "feb", "mar", "apr", "may", "jun", "jul"]; 141 | const config = { 142 | line: { 143 | visible: true, 144 | strokeWidth: 2, 145 | strokeColor: "#341f97" 146 | }, 147 | area: { 148 | visible: false 149 | }, 150 | yAxis: { 151 | visible: true, 152 | labelFormatter: v => String(v) + " °C" 153 | }, 154 | xAxis: { 155 | visible: true 156 | }, 157 | grid: { 158 | stepSize: 15 159 | }, 160 | dataPoint: { 161 | visible: true, 162 | color: "#777", 163 | radius: 3, 164 | label: { visible: true, marginBottom: 25 } 165 | }, 166 | insetY: 10 167 | }; 168 | ``` 169 | 170 | 171 | 172 | ```jsx 173 | const data4 = [-10, -15, 40, 19, 32, 15, 52, 55, 20, 60, 78, 42, 56]; 174 | const config4 = { 175 | interpolation: "spline", 176 | line: { strokeColor: "#be2ddd", strokeWidth: 2 }, 177 | yAxis: { visible: false }, 178 | grid: { visible: false } 179 | }; 180 | ``` 181 | 182 | 183 | 184 | ````jsx 185 | const data5 = [-10, -15, 40, 19, 32, 15, 52, 55, 20, 60, 78, 42, 56]; 186 | const config5 = { 187 | interpolation: 'spline', 188 | area: { 189 | gradientFrom: '#10ac84', 190 | gradientFromOpacity: 1, 191 | gradientTo: '#10ac84', 192 | gradientToOpacity: 0.4, 193 | }, 194 | line: { 195 | visible: false 196 | } 197 | }``` 198 | 199 | Note: the cards around the charts are not included. 200 | ```` 201 | 202 | Image for maintainers 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-responsive-linechart 2 | 3 |     4 | 5 | ## Announcing v5 6 | 7 | Breaking changes with respect to v4: 8 | 9 | - New dependency on `react-native-gesture-handler` 10 | 11 | Breaking changes with respect to v3: 12 | 13 | - Support for data point visualizations 14 | - Library supplied tooltip component is renamed from `BoxTooltip` to just `Tooltip` 15 | - Minor theme changes (box -> shape rename) 16 | 17 | Additional features: 18 | - Scrollable charts! 19 | 20 | ## [View installation docs & examples here](https://react-native-responsive-linechart.surge.sh) 21 | 22 | ### Screenshots 23 | 24 |  25 |  26 |  27 |  28 |  29 | 30 | ### Quick example 31 | 32 | ```javascript 33 | import { Chart, VerticalAxis, HorizontalAxis, Line } from 'react-native-responsive-linechart' 34 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | const data1 = [ 48 | { x: -2, y: 1 }, 49 | { x: -1, y: 0 }, 50 | { x: 8, y: 13 }, 51 | { x: 9, y: 11.5 }, 52 | { x: 10, y: 12 } 53 | ] 54 | 55 | const data2 = [ 56 | { x: -2, y: 15 }, 57 | { x: -1, y: 10 }, 58 | { x: 0, y: 12 }, 59 | { x: 1, y: 7 }, 60 | { x: 8, y: 12 }, 61 | { x: 9, y: 13.5 }, 62 | { x: 10, y: 18 } 63 | ] 64 | ``` 65 | 66 | 67 | ## [OLD] Announcing v3 68 | 69 | Version 3 is a complete re-write from the ground up with the following exciting features: 70 | 71 | - Completely written in Typescript 72 | - Composable API, every part of the chart is its own component. 73 | - Very few dependencies (Total package size is only 62 kilobytes) 74 | - New documentation website with extensive examples 75 | - Support for smooth/linear line & charts area charts, tooltips and more 76 | 77 | Due to the nature of the changes, version 2.2 and below is now no longer supported. You can find the [old README here](https://github.com/N1ghtly/react-native-responsive-linechart/blob/master/README-v2.2.md). 78 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | // babel.config.js 2 | module.exports = { 3 | presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'] 4 | } 5 | -------------------------------------------------------------------------------- /demo/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /demo/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | parser: '@typescript-eslint/parser', 5 | plugins: ['@typescript-eslint'], 6 | }; 7 | -------------------------------------------------------------------------------- /demo/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # Visual Studio Code 33 | # 34 | .vscode/ 35 | 36 | # node.js 37 | # 38 | node_modules/ 39 | npm-debug.log 40 | yarn-error.log 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | !debug.keystore 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://docs.fastlane.tools/best-practices/source-control/ 54 | 55 | */fastlane/report.xml 56 | */fastlane/Preview.html 57 | */fastlane/screenshots 58 | 59 | # Bundle artifact 60 | *.jsbundle 61 | 62 | # CocoaPods 63 | /ios/Pods/ 64 | -------------------------------------------------------------------------------- /demo/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /demo/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import styled from 'styled-components/native' 3 | import { StatusBar, Text, TouchableOpacity } from 'react-native' 4 | import { Chart, HorizontalAxis, VerticalAxis, Line, Area, Tooltip } from 'react-native-responsive-linechart' 5 | 6 | const App = () => { 7 | const ref = React.useRef() 8 | const ref2 = React.useRef() 9 | 10 | return ( 11 | 12 | 13 | ref?.current?.setTooltipIndex(1)}> 14 | Set tooltip to second datapoint 15 | 16 | ref?.current?.setTooltipIndex(undefined)}> 17 | Hide tooltip 18 | 19 | ref2?.current?.setViewportOrigin({ x: 0, y: 0 })}> 20 | Set viewport to start 21 | 22 | ref2?.current?.setViewportOrigin({ x: 5, y: 0 })}> 23 | Set viewport to end 24 | 25 | 46 | v.toFixed(2) }, grid: { stroke: { dashArray: [10, 2] } } }} /> 47 | 48 | 49 | } 56 | theme={{ 57 | stroke: { color: '#44bd32', width: 5 }, 58 | scatter: { default: { width: 8, height: 8, rx: 4, color: '#44ad32' }, selected: { color: 'red' } }, 59 | }} 60 | /> 61 | 62 | 68 | v.toFixed(2) } }} /> 69 | 70 | 83 | 97 | 98 | 107 | v.toFixed(2) }, 113 | }} 114 | /> 115 | v.toFixed(1) }, 121 | }} 122 | /> 123 | 124 | 130 | {/* 131 | 132 | */} 133 | 134 | 152 | v.toFixed(2) } }} /> 153 | 154 | 155 | 156 | 157 | 158 | 169 | v.toFixed(2) }, 175 | }} 176 | /> 177 | v.toFixed(1) }, 183 | }} 184 | /> 185 | 186 | 187 | 188 | } /> 189 | 190 | 191 | ) 192 | } 193 | 194 | export default App 195 | 196 | const Container = styled.ScrollView.attrs(() => ({ contentContainerStyle: { paddingBottom: 64, paddingTop: 32 } }))` 197 | width: 100%; 198 | flex: 1; 199 | padding: 24px; 200 | background-color: #fff; 201 | ` 202 | 203 | const data1 = [ 204 | { x: 5, y: 15 }, 205 | { x: 6, y: 6 }, 206 | { x: 7, y: 15 }, 207 | { x: 8, y: 3 }, 208 | ] 209 | 210 | const data2 = new Array(500).fill(undefined).map((v, i) => ({ x: i / 10, y: Math.random() * 10 + 5 })) 211 | -------------------------------------------------------------------------------- /demo/android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | LineChartDemo 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /demo/android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | arguments= 2 | auto.sync=false 3 | build.scans.enabled=false 4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) 5 | connection.project.dir= 6 | eclipse.preferences.version=1 7 | gradle.user.home= 8 | java.home=/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home 9 | jvm.arguments= 10 | offline.mode=false 11 | override.workspace.settings=true 12 | show.console.view=true 13 | show.executions.view=true 14 | -------------------------------------------------------------------------------- /demo/android/app/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo/android/app/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /demo/android/app/_BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.linechartdemo", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.linechartdemo", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /demo/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation. If none specified and 19 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is 20 | * // default. Can be overridden with ENTRY_FILE environment variable. 21 | * entryFile: "index.android.js", 22 | * 23 | * // https://reactnative.dev/docs/performance#enable-the-ram-format 24 | * bundleCommand: "ram-bundle", 25 | * 26 | * // whether to bundle JS and assets in debug mode 27 | * bundleInDebug: false, 28 | * 29 | * // whether to bundle JS and assets in release mode 30 | * bundleInRelease: true, 31 | * 32 | * // whether to bundle JS and assets in another build variant (if configured). 33 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 34 | * // The configuration property can be in the following formats 35 | * // 'bundleIn${productFlavor}${buildType}' 36 | * // 'bundleIn${buildType}' 37 | * // bundleInFreeDebug: true, 38 | * // bundleInPaidRelease: true, 39 | * // bundleInBeta: true, 40 | * 41 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 42 | * // for example: to disable dev mode in the staging build type (if configured) 43 | * devDisabledInStaging: true, 44 | * // The configuration property can be in the following formats 45 | * // 'devDisabledIn${productFlavor}${buildType}' 46 | * // 'devDisabledIn${buildType}' 47 | * 48 | * // the root of your project, i.e. where "package.json" lives 49 | * root: "../../", 50 | * 51 | * // where to put the JS bundle asset in debug mode 52 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 53 | * 54 | * // where to put the JS bundle asset in release mode 55 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 56 | * 57 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 58 | * // require('./image.png')), in debug mode 59 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 60 | * 61 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 62 | * // require('./image.png')), in release mode 63 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 64 | * 65 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 66 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 67 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 68 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 69 | * // for example, you might want to remove it from here. 70 | * inputExcludes: ["android/**", "ios/**"], 71 | * 72 | * // override which node gets called and with what additional arguments 73 | * nodeExecutableAndArgs: ["node"], 74 | * 75 | * // supply additional arguments to the packager 76 | * extraPackagerArgs: [] 77 | * ] 78 | */ 79 | 80 | project.ext.react = [ 81 | enableHermes: false, // clean and rebuild if changing 82 | ] 83 | 84 | apply from: "../../node_modules/react-native/react.gradle" 85 | 86 | /** 87 | * Set this to true to create two separate APKs instead of one: 88 | * - An APK that only works on ARM devices 89 | * - An APK that only works on x86 devices 90 | * The advantage is the size of the APK is reduced by about 4MB. 91 | * Upload all the APKs to the Play Store and people will download 92 | * the correct one based on the CPU architecture of their device. 93 | */ 94 | def enableSeparateBuildPerCPUArchitecture = false 95 | 96 | /** 97 | * Run Proguard to shrink the Java bytecode in release builds. 98 | */ 99 | def enableProguardInReleaseBuilds = false 100 | 101 | /** 102 | * The preferred build flavor of JavaScriptCore. 103 | * 104 | * For example, to use the international variant, you can use: 105 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 106 | * 107 | * The international variant includes ICU i18n library and necessary data 108 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 109 | * give correct results when using with locales other than en-US. Note that 110 | * this variant is about 6MiB larger per architecture than default. 111 | */ 112 | def jscFlavor = 'org.webkit:android-jsc:+' 113 | 114 | /** 115 | * Whether to enable the Hermes VM. 116 | * 117 | * This should be set on project.ext.react and mirrored here. If it is not set 118 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 119 | * and the benefits of using Hermes will therefore be sharply reduced. 120 | */ 121 | def enableHermes = project.ext.react.get("enableHermes", false); 122 | 123 | android { 124 | compileSdkVersion rootProject.ext.compileSdkVersion 125 | 126 | compileOptions { 127 | sourceCompatibility JavaVersion.VERSION_1_8 128 | targetCompatibility JavaVersion.VERSION_1_8 129 | } 130 | 131 | defaultConfig { 132 | applicationId "com.linechartdemo" 133 | minSdkVersion rootProject.ext.minSdkVersion 134 | targetSdkVersion rootProject.ext.targetSdkVersion 135 | versionCode 1 136 | versionName "1.0" 137 | } 138 | splits { 139 | abi { 140 | reset() 141 | enable enableSeparateBuildPerCPUArchitecture 142 | universalApk false // If true, also generate a universal APK 143 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 144 | } 145 | } 146 | signingConfigs { 147 | debug { 148 | storeFile file('debug.keystore') 149 | storePassword 'android' 150 | keyAlias 'androiddebugkey' 151 | keyPassword 'android' 152 | } 153 | } 154 | buildTypes { 155 | debug { 156 | signingConfig signingConfigs.debug 157 | } 158 | release { 159 | // Caution! In production, you need to generate your own keystore file. 160 | // see https://reactnative.dev/docs/signed-apk-android. 161 | signingConfig signingConfigs.debug 162 | minifyEnabled enableProguardInReleaseBuilds 163 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 164 | } 165 | } 166 | 167 | // applicationVariants are e.g. debug, release 168 | applicationVariants.all { variant -> 169 | variant.outputs.each { output -> 170 | // For each separate APK per architecture, set a unique version code as described here: 171 | // https://developer.android.com/studio/build/configure-apk-splits.html 172 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 173 | def abi = output.getFilter(OutputFile.ABI) 174 | if (abi != null) { // null for the universal-debug, universal-release variants 175 | output.versionCodeOverride = 176 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 177 | } 178 | 179 | } 180 | } 181 | } 182 | 183 | dependencies { 184 | implementation fileTree(dir: "libs", include: ["*.jar"]) 185 | //noinspection GradleDynamicVersion 186 | implementation "com.facebook.react:react-native:+" // From node_modules 187 | 188 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" 189 | 190 | 191 | if (enableHermes) { 192 | def hermesPath = "../../node_modules/hermes-engine/android/"; 193 | debugImplementation files(hermesPath + "hermes-debug.aar") 194 | releaseImplementation files(hermesPath + "hermes-release.aar") 195 | } else { 196 | implementation jscFlavor 197 | } 198 | } 199 | 200 | // Run this once to be able to run the application with BUCK 201 | // puts all compile dependencies into folder libs for BUCK to use 202 | task copyDownloadableDepsToLibs(type: Copy) { 203 | from configurations.compile 204 | into 'libs' 205 | } 206 | 207 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 208 | -------------------------------------------------------------------------------- /demo/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /demo/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/debug.keystore -------------------------------------------------------------------------------- /demo/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /demo/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demo/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /demo/android/app/src/main/java/com/linechartdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.linechartdemo; 2 | 3 | import com.facebook.react.ReactActivityDelegate; 4 | import com.facebook.react.ReactRootView; 5 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; 6 | import com.facebook.react.ReactActivity; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is 12 | * used to schedule rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "LineChartDemo"; 17 | } 18 | 19 | @Override 20 | protected ReactActivityDelegate createReactActivityDelegate() { 21 | return new ReactActivityDelegate(this, getMainComponentName()) { 22 | @Override 23 | protected ReactRootView createRootView() { 24 | return new RNGestureHandlerEnabledRootView(MainActivity.this); 25 | } 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /demo/android/app/src/main/java/com/linechartdemo/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.linechartdemo; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactInstanceManager; 8 | import com.facebook.react.ReactNativeHost; 9 | import com.facebook.react.ReactPackage; 10 | import com.facebook.soloader.SoLoader; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.util.List; 13 | 14 | public class MainApplication extends Application implements ReactApplication { 15 | 16 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 17 | @Override 18 | public boolean getUseDeveloperSupport() { 19 | return BuildConfig.DEBUG; 20 | } 21 | 22 | @Override 23 | protected List getPackages() { 24 | @SuppressWarnings("UnnecessaryLocalVariable") 25 | List packages = new PackageList(this).getPackages(); 26 | // Packages that cannot be autolinked yet can be added manually here, for 27 | // example: 28 | // packages.add(new MyReactNativePackage()); 29 | return packages; 30 | } 31 | 32 | @Override 33 | protected String getJSMainModuleName() { 34 | return "index"; 35 | } 36 | }; 37 | 38 | @Override 39 | public ReactNativeHost getReactNativeHost() { 40 | return mReactNativeHost; 41 | } 42 | 43 | @Override 44 | public void onCreate() { 45 | super.onCreate(); 46 | SoLoader.init(this, /* native exopackage */ false); 47 | // initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demo/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | LineChartDemo 3 | 4 | -------------------------------------------------------------------------------- /demo/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /demo/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "29.0.2" 6 | minSdkVersion = 16 7 | compileSdkVersion = 29 8 | targetSdkVersion = 29 9 | } 10 | repositories { 11 | google() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle:3.5.3") 16 | // NOTE: Do not place your application dependencies here; they belong 17 | // in the individual module build.gradle files 18 | } 19 | } 20 | 21 | allprojects { 22 | repositories { 23 | mavenLocal() 24 | maven { 25 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 26 | url("$rootDir/../node_modules/react-native/android") 27 | } 28 | maven { 29 | // Android JSC is installed from npm 30 | url("$rootDir/../node_modules/jsc-android/dist") 31 | } 32 | 33 | google() 34 | jcenter() 35 | maven { url 'https://www.jitpack.io' } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /demo/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.66.0 29 | -------------------------------------------------------------------------------- /demo/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/demo/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /demo/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /demo/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" 184 | -------------------------------------------------------------------------------- /demo/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | @rem Execute Gradle 88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 89 | 90 | :end 91 | @rem End local scope for the variables with windows NT shell 92 | if "%ERRORLEVEL%"=="0" goto mainEnd 93 | 94 | :fail 95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 96 | rem the _cmd.exe /c_ return code! 97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 98 | exit /b 1 99 | 100 | :mainEnd 101 | if "%OS%"=="Windows_NT" endlocal 102 | 103 | :omega 104 | -------------------------------------------------------------------------------- /demo/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'LineChartDemo' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /demo/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LineChartDemo", 3 | "displayName": "LineChartDemo" 4 | } -------------------------------------------------------------------------------- /demo/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /demo/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo.xcodeproj/xcshareddata/xcschemes/LineChartDemo-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo.xcodeproj/xcshareddata/xcschemes/LineChartDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | 7 | #ifdef FB_SONARKIT_ENABLED 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | 15 | static void InitializeFlipper(UIApplication *application) { 16 | FlipperClient *client = [FlipperClient sharedClient]; 17 | SKDescriptorMapper *layoutDescriptorMapper = 18 | [[SKDescriptorMapper alloc] initWithDefaults]; 19 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] 20 | initWithRootNode:application 21 | withDescriptorMapper:layoutDescriptorMapper]]; 22 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 23 | [client addPlugin:[FlipperKitReactPlugin new]]; 24 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] 25 | initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 26 | [client start]; 27 | } 28 | #endif 29 | 30 | @implementation AppDelegate 31 | 32 | - (BOOL)application:(UIApplication *)application 33 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 34 | #ifdef FB_SONARKIT_ENABLED 35 | InitializeFlipper(application); 36 | #endif 37 | 38 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self 39 | launchOptions:launchOptions]; 40 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 41 | moduleName:@"LineChartDemo" 42 | initialProperties:nil]; 43 | 44 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f 45 | green:1.0f 46 | blue:1.0f 47 | alpha:1]; 48 | 49 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 50 | UIViewController *rootViewController = [UIViewController new]; 51 | rootViewController.view = rootView; 52 | self.window.rootViewController = rootViewController; 53 | [self.window makeKeyAndVisible]; 54 | return YES; 55 | } 56 | 57 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { 58 | #ifdef FB_SONARKIT_ENABLED 59 | return 60 | [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" 61 | fallbackResource:nil]; 62 | #else 63 | return [[NSBundle mainBundle] URLForResource:@"main" 64 | withExtension:@"jsbundle"]; 65 | #endif 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | LineChartDemo 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemo/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo/ios/LineChartDemoTests/LineChartDemoTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface LineChartDemoTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation LineChartDemoTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 38 | if (level >= RCTLogLevelError) { 39 | redboxError = message; 40 | } 41 | }); 42 | #endif 43 | 44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | 48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 50 | return YES; 51 | } 52 | return NO; 53 | }]; 54 | } 55 | 56 | #ifdef DEBUG 57 | RCTSetLogFunction(RCTDefaultLogFunction); 58 | #endif 59 | 60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /demo/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '10.0' 5 | 6 | target 'LineChartDemo' do 7 | config = use_native_modules! 8 | 9 | use_react_native!(:path => config["reactNativePath"]) 10 | 11 | target 'LineChartDemoTests' do 12 | inherit! :complete 13 | # Pods for testing 14 | end 15 | 16 | # Enables Flipper. 17 | # 18 | # Note that if you have use_frameworks! enabled, Flipper will not work and 19 | # you should disable these next few lines. 20 | use_flipper! 21 | post_install do |installer| 22 | flipper_post_install(installer) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /demo/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | const path = require('path') 9 | 10 | const extraNodeModules = { 11 | 'react-native-responsive-linechart': path.resolve(__dirname + '/../src'), 12 | } 13 | 14 | const watchFolders = [path.resolve(__dirname + '/../src')] 15 | 16 | module.exports = { 17 | transformer: { 18 | getTransformOptions: async () => ({ 19 | transform: { 20 | experimentalImportSupport: true, 21 | inlineRequires: false, 22 | }, 23 | }), 24 | }, 25 | resolver: { 26 | extraNodeModules: new Proxy(extraNodeModules, { 27 | get: (target, name) => 28 | //redirects dependencies referenced from common/ to local node_modules 29 | name in target ? target[name] : path.join(process.cwd(), `node_modules/${name}`), 30 | }), 31 | }, 32 | watchFolders, 33 | } 34 | -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-responsive-linechart-demo", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios --simulator='iPhone 12'", 8 | "start": "react-native start", 9 | "test": "jest", 10 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx" 11 | }, 12 | "dependencies": { 13 | "@yr/monotone-cubic-spline": "^1.0.3", 14 | "deepmerge": "^4.2.2", 15 | "fast-deep-equal": "^3.1.3", 16 | "lodash.clamp": "^4.0.3", 17 | "lodash.clonedeep": "^4.5.0", 18 | "lodash.debounce": "^4.0.8", 19 | "lodash.maxby": "^4.6.0", 20 | "lodash.minby": "^4.6.0", 21 | "paths-js": "^0.4.11", 22 | "react": "17.0.1", 23 | "react-native": "0.63.3", 24 | "react-native-gesture-handler": "^1.9.0", 25 | "react-native-svg": "^12.1.0", 26 | "styled-components": "^5.2.1" 27 | }, 28 | "devDependencies": { 29 | "@babel/core": "^7.12.9", 30 | "@babel/runtime": "^7.12.5", 31 | "@react-native-community/eslint-config": "^2.0.0", 32 | "@types/jest": "^26.0.15", 33 | "@types/react": "^17.0.0", 34 | "@types/react-native": "^0.63.37", 35 | "@types/react-test-renderer": "^17.0.0", 36 | "@types/styled-components": "^5.1.4", 37 | "@typescript-eslint/eslint-plugin": "^4.8.2", 38 | "@typescript-eslint/parser": "^4.8.2", 39 | "babel-jest": "^26.6.3", 40 | "eslint": "^7.14.0", 41 | "jest": "^26.6.3", 42 | "metro-react-native-babel-preset": "^0.64.0", 43 | "prettier": "^2.2.0", 44 | "react-test-renderer": "17.0.1", 45 | "typescript": "^4.1.2" 46 | }, 47 | "jest": { 48 | "preset": "react-native", 49 | "moduleFileExtensions": [ 50 | "ts", 51 | "tsx", 52 | "js", 53 | "jsx", 54 | "json", 55 | "node" 56 | ] 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "resolveJsonModule": true, 4 | /* Basic Options */ 5 | "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, 6 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 7 | "lib": ["es6"] /* Specify library files to be included in the compilation. */, 8 | "allowJs": true /* Allow javascript files to be compiled. */, 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | "jsx": "react-native" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, 11 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | // "outDir": "./", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "removeComments": true, /* Do not emit comments to output. */ 17 | "noEmit": true /* Do not emit outputs. */, 18 | // "incremental": true, /* Enable incremental compilation */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */, 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true /* Enable all strict type-checking options. */, 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | 32 | /* Additional Checks */ 33 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 34 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 35 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 36 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 37 | 38 | /* Module Resolution Options */ 39 | "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, 40 | "baseUrl": "./" /* Base directory to resolve non-absolute module names. */, 41 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 42 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 43 | // "typeRoots": [], /* List of folders to include type definitions from. */ 44 | // "types": [], /* Type declaration files to be included in compilation. */ 45 | "allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */, 46 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 47 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 48 | 49 | /* Source Map Options */ 50 | // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 51 | // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ 52 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 53 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 54 | 55 | /* Experimental Options */ 56 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 57 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 58 | }, 59 | "paths": { 60 | "react-native-responsive-linechart": ["../src/index.ts"], 61 | "react-native-responsive-linechart/*": ["../src/*"] 62 | }, 63 | "include": ["../src/**/*.tsx", "../src/**/*.ts", "./**/*.ts", "./**/*.tsx", "index.js"], 64 | "exclude": ["node_modules", "babel.config.js", "metro.config.js", "jest.config.js"] 65 | } 66 | -------------------------------------------------------------------------------- /deploy_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | cd docusaurus 4 | yarn build 5 | echo react-native-responsive-linechart.surge.sh > build/CNAME 6 | cd build 7 | echo -ne '\n' | surge -------------------------------------------------------------------------------- /docusaurus/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docusaurus/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /docusaurus/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | } 4 | -------------------------------------------------------------------------------- /docusaurus/blog/2020-08-17-welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: announcement-v3 3 | title: Announcing v3 4 | author: Xander Deseyn 5 | author_title: Co-Founder @ Devizer 6 | author_url: https://github.com/n1ghtly 7 | author_image_url: https://avatars2.githubusercontent.com/u/1395284?s=460&u=a8bb2bbfe9d96c6d3e7ba80cf3091da352081d7d&v=4 8 | tags: [announcement] 9 | --- 10 | 11 | 12 | Version 3 is a complete re-write from the ground up with the following exciting features: 13 | 14 | - Completely written in **Typescript** 15 | - **Composable API**, every part of the chart is its own component. 16 | - Very few dependencies (total package size is only **62 kilobytes**) 17 | - New **documentation website** with extensive examples 18 | 19 | Due to the nature of the changes, version 2.2 and below is now no longer supported. You can find the [old docs here](https://github.com/N1ghtly/react-native-responsive-linechart/blob/master/README-v2.2.md). 20 | -------------------------------------------------------------------------------- /docusaurus/blog/2020-10-1-v5.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: announcement-v5 3 | title: Announcing v5 4 | author: Xander Deseyn 5 | author_title: Co-Founder @ Devizer 6 | author_url: https://github.com/n1ghtly 7 | author_image_url: https://avatars2.githubusercontent.com/u/1395284?s=460&u=a8bb2bbfe9d96c6d3e7ba80cf3091da352081d7d&v=4 8 | tags: [announcement] 9 | --- 10 | 11 | 12 | Announcing v5 13 | 14 | Breaking changes with respect to v4: 15 | 16 | - New dependency on react-native-gesture-handler 17 | 18 | Breaking changes with respect to v3: 19 | 20 | - Support for data point visualizations 21 | - Library supplied tooltip component is renamed from BoxTooltip to just Tooltip 22 | - Minor theme changes (box -> shape rename) 23 | 24 | New features: 25 | 26 | - Scrollable charts! -------------------------------------------------------------------------------- /docusaurus/docs/area.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: Area 4 | id: area 5 | route: /area 6 | 7 | --- 8 | 9 | This component draws an area. Multiple areas can be drawn on one chart. 10 | 11 | ## Area Props 12 | | Prop | Type | Required | Description 13 | | ----------- | ----------- | ------------- | ------ | 14 | | `data` | `{ x: number, y: number, meta?: any }[]` | Yes* | Data for the chart. Overrides optional data provided in ``. | 15 | | `smoothing` | "none" \| "cubic-spline" \| "bezier" | No | `none` is just linear lines. `cubic-spline` is usually the most aesthetically pleasing smoothing. | 16 | | `tension` | `number` | No | Only works in combination with smoothing='bezier'. Value between 0 and 1, recommended somewhere around `0.3`. | 17 | | `theme` | Defined below | No | Theme for the area. | 18 | 19 | \* unless provided in parent `` component 20 | 21 | ### Area default theme 22 | Any part of this theme can be overridden through the `theme` prop. 23 | ```json 24 | { 25 | gradient: { 26 | from: { 27 | color: 'red', 28 | opacity: 1 29 | }, 30 | to: { 31 | color: 'red', 32 | opacity: 0.2 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ## Examples 39 | 40 | ### Combined with `` 41 | 42 |  43 | 44 | ```jsx 45 | 66 | v.toFixed(2) } }} /> 67 | 68 | 69 | 70 | 71 | ``` 72 | 73 | ### Multiple areas and `smoothing` 74 | 75 |  76 | 77 | ```jsx 78 | 84 | v.toFixed(2) } }} 87 | /> 88 | 89 | 102 | 116 | 117 | ``` -------------------------------------------------------------------------------- /docusaurus/docs/chart.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: Chart 4 | id: chart 5 | route: /chart 6 | 7 | --- 8 | 9 | This component should **always** be wrapped around any other component from this library, since it is responsible for constructing the chart context. 10 | 11 | ## Chart Props 12 | | Prop | Type | Required | Description 13 | | ----------- | ----------- | ------------- | ------ | 14 | | `data` | `{ x: number, y: number, meta?: any }[]` | No | Chart data points to be passed to `Area` or `Line` children. Not required, and can be overridden in child components. | 15 | | `style` | `ViewStyle` | No | All styling can be used except for padding. If you need padding, use the explicit `padding` prop below | 16 | | `xDomain` | `{ min: number, max: number }` | Yes* | Domain for the horizontal (X) axis. | 17 | | `yDomain` | `{ min: number, max: number }` | Yes* | Domain for the horizontal (Y) axis. | 18 | | `viewport` | `{ initialOrigin: { x: number, y: number }, size: { width: number, height: number } }` | No | The Viewport defines what part of the chart is visible. Defaults to the full domain in both axes. This is used [if you want the chart to be scrollable.](line.md#with-viewport-scrollable-chart) | 19 | | `disableTouch` | `{ min: number, max: number }` | No | Disables touch responder for the chart. You can disable it if you don't need tooltips. | 20 | | `disableGestures` | `boolean` | No | Disables gestures for the chart. You can disable it if you don't need scrolling in the chart (with viewport). | 21 | | `padding` | `{ left?: number; right?: number; top?: number; bottom?: number }` | No | Padding of the chart. Use this instead of setting padding in the `style` prop. | 22 | 23 | \* Props can be left out if `data` prop is provided. Domain will automatically be set to the data bounds. 24 | 25 | 26 | ## Chart Methods 27 | | Method | Description 28 | | ----------- | ------ | 29 | | `setViewportOrigin({ x: number, y: number })` | Imperatively set the viewport origin of the chart. (example in demo project) | 30 | 31 | 32 | ### Example 33 | 34 |  35 | 36 | ```jsx 37 | 54 | v.toFixed(2) } }} 57 | /> 58 | 59 | 60 | 61 | 62 | ``` 63 | 64 | For more advanced examples, check out the Area and Line pages. -------------------------------------------------------------------------------- /docusaurus/docs/gettingstarted.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | slug: / 4 | title: Getting started 5 | id: gettingstarted 6 | 7 | --- 8 | 9 | If you are looking for the documentation of version 2, [you can find it here](https://github.com/react-native-community/react-native-svg). 10 | Version 3 is a complete re-write from the ground up, in typescript. 11 | 12 | ## Installation 13 | 14 | `npm install react-native-responsive-linechart` or `yarn add react-native-responsive-linechart` 15 | 16 | This lib depends on [react-native-svg](https://github.com/react-native-community/react-native-svg) and [react-native-gesture-handler](https://github.com/software-mansion/react-native-gesture-handler), so make sure that is installed correctly. 17 | 18 | ## Getting started 19 | 20 | Head over to the [Chart component](chart.md) to start learning the API, or check out the code below to get up and running quickly. 21 | 22 | ## Code example 23 | 24 | For more advanced examples, check out the [Line](line.md) and [Area](area.md) docs. 25 | 26 |  27 | 28 | 29 | ```jsx 30 | import { Chart, Line, Area, HorizontalAxis, VerticalAxis } from 'react-native-responsive-linechart' 31 | 32 | 53 | v.toFixed(2) } }} /> 54 | 55 | 56 | 57 | 58 | ``` 59 | -------------------------------------------------------------------------------- /docusaurus/docs/horizontalaxis.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: HorizontalAxis 4 | id: horizontalaxis 5 | route: /horizontalaxis 6 | 7 | --- 8 | 9 | This component draws an axis on the X plane. 10 | 11 | 12 | ## HorizontalAxis Props 13 | | Prop | Type | Required | Description 14 | | ----------- | ----------- | ------------- | ------ | 15 | | `tickValues` | `number[]` | No | Use this to explicitly set the ticks which should be drawn on the axis. | 16 | | `tickCount` | `number[]` | No | Use this if you always want to render X amount of ticks on the axis. The lib will calculate the tick values itself. | 17 | | `includeOriginTick` | `boolean` | No | Only relevant in combination with the `tickCount` prop. Defaults to `true`. Check verticalaxis example. | 18 | | `theme` | Defined below | No | Theme for the line. | 19 | 20 | ### HorizontalAxis default theme 21 | Any part of this theme can be overridden through the `theme` prop. 22 | 23 | ```json 24 | { 25 | axis: { 26 | visible: true, 27 | stroke: { 28 | color: '#bbb', 29 | width: 2, 30 | opacity: 1, 31 | dashArray: [] 32 | }, 33 | dy: 0, 34 | }, 35 | grid: { 36 | visible: true, 37 | stroke: { 38 | color: '#ccc', 39 | width: 1, 40 | opacity: 1, 41 | dashArray: [] 42 | }, 43 | }, 44 | ticks: { 45 | visible: true, 46 | stroke: { 47 | color: '#000', 48 | width: 1, 49 | opacity: 1, 50 | }, 51 | dy: 0, 52 | length: 6, 53 | includeOriginTick: false, 54 | }, 55 | labels: { 56 | visible: true, 57 | label: { 58 | color: '#000', 59 | fontSize: 10, 60 | fontWeight: 300, 61 | textAnchor: 'middle', 62 | opacity: 1, 63 | dx: 0, 64 | dy: -12, 65 | rotation: 0, 66 | fontFamily: 'your font here' 67 | }, 68 | formatter: (v: number) => String(v), 69 | }, 70 | } 71 | ``` 72 | Use `dashArray` if you want to add dashes to the stroke (array of numbers). For the most basic use case, eg. 5px line, 5px open, 5px line, 5px open... just pass `[5]`. 73 | 74 | ## Examples 75 | 76 | 77 | 78 | ### with `tickValues` 79 | 80 |  81 | 82 | ```jsx 83 | 104 | 105 | 106 | 107 | ``` 108 | 109 | ### with `tickCount` and `includeOriginTick=false` 110 | 111 |  112 | 113 | ```jsx 114 | 135 | v.toFixed(2) } }} includeOriginTick={false} /> 136 | 137 | 138 | ``` 139 | -------------------------------------------------------------------------------- /docusaurus/docs/line.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: Line 4 | id: line 5 | route: /line 6 | 7 | --- 8 | 9 | This component draws a line. Multiple lines can be drawn on one chart. 10 | 11 | 12 | ## Line Props 13 | | Prop | Type | Required | Description 14 | | ----------- | ----------- | ------------- | ------ | 15 | | `data` | `{ x: number, y: number, meta?: any }[]` | Yes* | Data for the chart. Overrides optional data provided in ``. | 16 | | `smoothing` | `"none"` \| `"cubic-spline"` \| `"bezier"` | No | `none` is just linear lines. `cubic-spline` is usually the most aesthetically pleasing smoothing. | 17 | | `tension` | `number` | No | Only works in combination with smoothing = `bezier`. Value between 0 and 1, recommended somewhere around `0.3`. | 18 | | `tooltipComponent` | `JSX.Element` | No | Component to be used to draw tooltips. This library provides a basic tooltip with the `Tooltip` component. Example below. | 19 | | `onTooltipSelect` | `(value: { x: number, y: number, meta?: any }, index: number) => void` | No | Callback method that fires when a tooltip is displayed for a data point. | 20 | | `onTooltipSelectEnd` | `() => void` | No | Callback method that fires when the user stopped touching the chart. | 21 | | `hideTooltipAfter` | `number` | No | Defines a period in ms after which the tooltip should hide automatically. | 22 | | `hideTooltipOnDragEnd` | `boolean` | No | Set to true if the tooltip should be hidden immediately when the user stops dragging the chart. (Only dragging, on tap the tooltip remains!) | 23 | | `initialTooltipIndex` | `number` | No | Initial index for the tooltip. The tooltip will be immediately visible at this index on first render, without requiring user interaction. | 24 | | `theme` | Defined below | No | Theme for the line. | 25 | 26 | \* unless provided in parent `` component 27 | 28 | 29 | ## Line Methods 30 | | Method | Description 31 | | ----------- | ------ | 32 | | `setTooltipIndex(value: number \| undefined)` | Imperatively set the tooltip index. Pass `undefined` to hide the tooltip. | 33 | 34 | 35 | ### Line default theme 36 | Any part of this theme can be overridden through the `theme` prop. 37 | 38 | ```json 39 | { 40 | stroke: { 41 | color: 'black', 42 | width: 1, 43 | opacity: 1, 44 | dashArray: [] 45 | }, 46 | scatter: { 47 | default: { 48 | width: 0, 49 | height: 0, 50 | dx: 0, 51 | dy: 0, 52 | rx: 0, 53 | color: 'black', 54 | }, 55 | selected: { 56 | width: 0, 57 | height: 0, 58 | dx: 0, 59 | dy: 0, 60 | rx: 0, 61 | color: 'black' 62 | }, 63 | }, 64 | } 65 | ``` 66 | 67 | The `scatter` theme defines how data points should be visualised. Optionally, you can change the visualisation when a data point is selected. 68 | Use `dashArray` if you want to add dashes to the stroke (array of numbers). For the most basic use case, eg. 5px line, 5px open, 5px line, 5px open... just pass `[5]`. 69 | 70 | ## Examples 71 | 72 | 73 | 74 | ### Combined with `` and using scatter points 75 | 76 |  77 | 78 | ```jsx 79 | 100 | v.toFixed(2) } }} /> 101 | 102 | 103 | 104 | 105 | ``` 106 | 107 | ### Multiple lines and `smoothing` 108 | 109 |  110 | 111 | ```jsx 112 | 123 | v.toFixed(2) }, 129 | }} 130 | /> 131 | v.toFixed(1) }, 137 | }} 138 | /> 139 | 140 | 141 | 142 | 143 | 144 | 145 | ``` 146 | 147 | ### With `tooltipComponent` and large number of datapoints 148 | 149 |  150 | 151 | ```jsx 152 | 159 | v.toFixed(2) }, 165 | }} 166 | /> 167 | 175 | 176 | y.toFixed(2) }} />} /> 177 | 178 | ``` 179 | 180 | 181 | ### With `viewport` (scrollable chart) 182 | 183 |  184 | 185 | By setting the viewport to be smaller than the domain, you can make the chart scrollable. In this example, the viewport has a width of 5, while the x-domain has a range of 10. You can also change where the viewport initially starts with the `initialOrigin` attribute of the `viewport` prop. (Check [Chart props](chart.md#chart-props)) 186 | 187 | ```jsx 188 | 196 | v.toFixed(2) }, 202 | }} 203 | /> 204 | v.toFixed(1) }, 210 | }} 211 | /> 212 | 218 | 219 | 220 | ``` -------------------------------------------------------------------------------- /docusaurus/docs/screenshots.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: Screenshots 4 | id: screenshots 5 | 6 | --- 7 | 8 | To give you and idea of the options this library offers, here are some end results. 9 | 10 |  11 |  12 |  13 |  14 |  15 |  16 | 17 | 18 |  19 |  20 |  -------------------------------------------------------------------------------- /docusaurus/docs/screenshots/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/docs/screenshots/home.png -------------------------------------------------------------------------------- /docusaurus/docs/tooltip.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: Tooltip 4 | id: tooltip 5 | route: /tooltip 6 | 7 | --- 8 | 9 | Tooltips can only be used in combination with a Line component. 10 | **This library provides one example tooltip component `Tooltip`**. For advanced styling, it is recommended to implement your own Tooltip component. 11 | 12 | ## Tooltip Props 13 | | Prop | Type | Required | Description 14 | | ----------- | ----------- | ------------- | ------ | 15 | | `theme` | Defined below | No | Theme for the line. | 16 | 17 | 18 | ### Tooltip default theme 19 | Any part of this theme can be overridden through the `theme` prop. 20 | 21 | ```json 22 | { 23 | label: { 24 | color: 'white', 25 | fontSize: 12, 26 | fontWeight: 700, 27 | fontFamily: 'your font here' 28 | textAnchor: 'middle', 29 | opacity: 1, 30 | dx: 0, 31 | dy: 16.5, 32 | }, 33 | shape: { 34 | width: 30, 35 | height: 20, 36 | dx: 0, 37 | dy: 20, 38 | rx: 4, 39 | color: 'black', 40 | }, 41 | formatter: (v: ChartDataPoint) => String(v.y), 42 | }, 43 | ``` 44 | 45 | ## Creating your own Tooltip 46 | 47 | Your tooltip component will be provided with the following props: 48 | 49 | | Prop | Type | Description 50 | | ----------- | ----------- | ------------- | ------ | 51 | | `value` | `{ x: number, y: number, meta?: any }` | The value that the tooltip should represent. | 52 | | `position` | `{ x: number, y: number }` | The exact position of the data point on the chart. You can offset your component from this position. Check out the source of `Tooltip` for an example. | 53 | 54 | You can then simply substitute `` with your own component in the `tooltipComponent` prop! 55 | 56 | ## Examples 57 | 58 |  59 | 60 | ```jsx 61 | 82 | v.toFixed(2) } }} /> 83 | 84 | 85 | } 87 | theme={{ stroke: { color: '#44bd32', width: 5 }, scatter: { default: { width: 8, height: 8, rx: 4, color: '#44ad32' }, selected: { color: 'red' } } }} 88 | /> 89 | 90 | ``` 91 | -------------------------------------------------------------------------------- /docusaurus/docs/types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Types 3 | id: types 4 | route: /types 5 | --- 6 | 7 | Straight export from types.ts file. Some internal types may also be found here. 8 | 9 | ```jsx 10 | export type XYValue = { x: number; y: number } 11 | 12 | export type ChartDataPoint = XYValue & { meta?: any } 13 | 14 | export type Padding = { top?: number; left?: number; right?: number; bottom?: number } 15 | 16 | export type Dimensions = { top: number; left: number; width: number; height: number } 17 | 18 | export type AxisDomain = { min: number; max: number } 19 | 20 | export type Smoothing = 'none' | 'cubic-spline' | 'bezier' 21 | 22 | export type ChartDomain = { x: AxisDomain; y: AxisDomain } 23 | 24 | export type Stroke = { color?: string; width?: number; opacity?: number; dashArray?: number[] } 25 | 26 | export type ViewPort = { size: { width: number; height: number }; initialOrigin: XYValue } 27 | 28 | export type Shape = { 29 | color?: string 30 | width?: number 31 | height?: number 32 | dx?: number 33 | dy?: number 34 | rx?: number 35 | opacity?: number 36 | radius?: number 37 | border?: Stroke 38 | } 39 | 40 | export type Gradient = { from?: { color?: string; opacity?: number }; to?: { color?: string; opacity?: number } } 41 | 42 | export type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 43 | 44 | export type TextAnchor = 'start' | 'middle' | 'end' 45 | 46 | export type Label = { 47 | color?: string 48 | fontSize?: number 49 | opacity?: number 50 | dy?: number 51 | dx?: number 52 | fontWeight?: FontWeight 53 | textAnchor?: TextAnchor 54 | rotation?: number 55 | } 56 | 57 | export type ChartContext = { 58 | data: ChartDataPoint[] 59 | dimensions: Dimensions | undefined 60 | domain: ChartDomain 61 | viewportDomain: ChartDomain 62 | viewportOrigin: XYValue 63 | viewport: ViewPort 64 | lastTouch: TouchEvent | undefined 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /docusaurus/docs/verticalaxis.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | title: VerticalAxis 4 | route: /verticalaxis 5 | id: verticalaxis 6 | 7 | --- 8 | 9 | This component draws an axis on the Y plane. 10 | 11 | ## VerticalAxis Props 12 | | Prop | Type | Required | Description 13 | | ----------- | ----------- | ------------- | ------ | 14 | | `tickValues` | `number[]` | No | Use this to explicitly set the ticks which should be drawn on the axis. | 15 | | `tickCount` | `number[]` | No | Use this if you always want to render X amount of ticks on the axis. The lib will calculate the tick values itself. | 16 | | `includeOriginTick` | `boolean` | No | Only relevant in combination with the `tickCount` prop. Defaults to `true`. Check example below. | 17 | | `theme` | Defined below | No | Theme for the line. | 18 | 19 | ### VerticalAxis default theme 20 | Any part of this theme can be overridden through the `theme` prop. 21 | 22 | ```json 23 | { 24 | axis: { 25 | visible: true, 26 | stroke: { 27 | color: '#bbb', 28 | width: 2, 29 | opacity: 1, 30 | dashArray: [], 31 | }, 32 | dx: 0, 33 | }, 34 | grid: { 35 | visible: true, 36 | stroke: { 37 | color: '#ccc', 38 | width: 1, 39 | opacity: 1, 40 | dashArray: [], 41 | }, 42 | }, 43 | ticks: { 44 | visible: true, 45 | stroke: { 46 | color: '#000', 47 | width: 1, 48 | opacity: 1, 49 | }, 50 | dx: 0, 51 | length: 6, 52 | }, 53 | labels: { 54 | visible: true, 55 | label: { 56 | color: '#000', 57 | fontSize: 10, 58 | fontWeight: 300, 59 | textAnchor: 'end', 60 | opacity: 1, 61 | dx: -4, 62 | dy: 4, 63 | rotation: 0, 64 | fontFamily: 'your font here' 65 | }, 66 | formatter: (v: number) => String(v), 67 | } 68 | } 69 | ``` 70 | Use `dashArray` if you want to add dashes to the stroke (array of numbers). For the most basic use case, eg. 5px line, 5px open, 5px line, 5px open... just pass `[5]`. 71 | 72 | ## Examples 73 | 74 | 75 | 76 | ### with `tickValues` 77 |  78 | 79 | ```jsx 80 | 101 | 102 | 103 | 104 | ``` 105 | 106 | ### with `tickCount` and `includeOriginTick=false` 107 |  108 | 109 | ```jsx 110 | 131 | v.toFixed(2) } }} includeOriginTick={false} /> 132 | 133 | 134 | 135 | ``` 136 | 137 | 138 | ### with `tickCount` and `includeOriginTick=true` 139 | 140 |  141 | 142 | ```jsx 143 | 164 | v.toFixed(2) } }}/> 165 | 166 | 167 | ``` -------------------------------------------------------------------------------- /docusaurus/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'React Native Responsive Linechart', 3 | tagline: 'Charts for React Native on easy mode', 4 | url: 'https://react-native-responsive-linechart.surge.sh', 5 | baseUrl: '/', 6 | onBrokenLinks: 'throw', 7 | favicon: 'img/favicon.ico', 8 | organizationName: 'n1ghtly', // Usually your GitHub org/user name. 9 | projectName: 'react-native-responsive-linechart', // Usually your repo name. 10 | themeConfig: { 11 | sidebarCollapsible: false, 12 | navbar: { 13 | title: 'react-native-responsive-linechart', 14 | logo: { 15 | alt: 'My Site Logo', 16 | src: 'img/logo.svg', 17 | }, 18 | items: [ 19 | { 20 | to: 'docs', 21 | activeBasePath: 'docs', 22 | label: 'Docs', 23 | position: 'left', 24 | }, 25 | { to: 'blog', label: 'Blog', position: 'left' }, 26 | { 27 | href: 'https://github.com/N1ghtly/react-native-responsive-linechart', 28 | label: 'GitHub', 29 | position: 'right', 30 | }, 31 | ], 32 | }, 33 | footer: { 34 | style: 'dark', 35 | 36 | copyright: `Copyright © ${new Date().getFullYear()} react-native-responsive-linechart, Inc. Built with Docusaurus.`, 37 | }, 38 | }, 39 | presets: [ 40 | [ 41 | '@docusaurus/preset-classic', 42 | { 43 | docs: { 44 | sidebarPath: require.resolve('./sidebars.js'), 45 | // Please change this to your repo. 46 | editUrl: 'https://github.com/N1ghtly/react-native-responsive-linechart/edit/master/docusaurus/', 47 | }, 48 | blog: { 49 | showReadingTime: true, 50 | // Please change this to your repo. 51 | editUrl: 'https://github.com/N1ghtly/react-native-responsive-linechart/edit/master/docusaurus/blog/', 52 | }, 53 | theme: { 54 | customCss: require.resolve('./src/css/custom.css'), 55 | }, 56 | }, 57 | ], 58 | ], 59 | } 60 | -------------------------------------------------------------------------------- /docusaurus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docusaurus", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "serve": "docusaurus serve" 12 | }, 13 | "dependencies": { 14 | "@docusaurus/core": "2.0.0-alpha.69", 15 | "@docusaurus/preset-classic": "2.0.0-alpha.69", 16 | "@mdx-js/react": "^1.6.21", 17 | "clsx": "^1.1.1", 18 | "react": "^17.0.1", 19 | "react-dom": "^17.0.1" 20 | }, 21 | "browserslist": { 22 | "production": [ 23 | ">0.2%", 24 | "not dead", 25 | "not op_mini all" 26 | ], 27 | "development": [ 28 | "last 1 chrome version", 29 | "last 1 firefox version", 30 | "last 1 safari version" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docusaurus/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | docs: [ 3 | 'gettingstarted', 4 | 'screenshots', 5 | { type: 'category', label: 'Components', items: ['chart', 'line', 'area', 'verticalaxis', 'horizontalaxis', 'tooltip', 'types'] }, 6 | ], 7 | } 8 | -------------------------------------------------------------------------------- /docusaurus/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* You can override the default Infima variables here. */ 9 | :root { 10 | --ifm-color-primary: #3498db; 11 | --ifm-color-primary-dark: #258bcf; 12 | --ifm-color-primary-darker: #2383c4; 13 | --ifm-color-primary-darkest: #1d6ca1; 14 | --ifm-color-primary-light: #4ba4df; 15 | --ifm-color-primary-lighter: #57aae1; 16 | --ifm-color-primary-lightest: #79bbe7; 17 | --ifm-code-font-size: 80%; 18 | } 19 | 20 | .docusaurus-highlight-code-line { 21 | background-color: rgb(72, 77, 91); 22 | display: block; 23 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 24 | padding: 0 var(--ifm-pre-padding); 25 | } 26 | -------------------------------------------------------------------------------- /docusaurus/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import clsx from 'clsx' 3 | import Layout from '@theme/Layout' 4 | import Link from '@docusaurus/Link' 5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext' 6 | import useBaseUrl from '@docusaurus/useBaseUrl' 7 | import styles from './styles.module.css' 8 | 9 | const features = [ 10 | { 11 | title: <>Written in Typescript>, 12 | imageUrl: 'img/typescript.svg', 13 | description: <>This library is 100% written in Typescript, types are bundled with the package.>, 14 | }, 15 | { 16 | title: <>Composable API>, 17 | imageUrl: 'img/source.png', 18 | description: <>Every part of the chart has its own component. This allows you to easily compose your chart with the features you need.>, 19 | }, 20 | { 21 | title: <>Small package size>, 22 | imageUrl: 'img/box.svg', 23 | description: <>Almost no dependencies, total package size is only 62 kilobytes unzipped.>, 24 | }, 25 | ] 26 | 27 | function Feature({ imageUrl, title, description }) { 28 | const imgUrl = useBaseUrl(imageUrl) 29 | return ( 30 | 31 | {imgUrl && ( 32 | 33 | 34 | 35 | )} 36 | {title} 37 | {description} 38 | 39 | ) 40 | } 41 | 42 | function Home() { 43 | const context = useDocusaurusContext() 44 | const { siteConfig = {} } = context 45 | return ( 46 | 47 | 48 | 49 | 50 | {siteConfig.title} 51 | 52 | 53 | {siteConfig.tagline} 54 | 55 | 56 | 57 | Get Started 58 | 59 | 60 | 61 | 62 | 63 | 64 | Screenshots 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | Features 73 | {features && features.length > 0 && ( 74 | 75 | 76 | 77 | {features.map((props, idx) => ( 78 | 79 | ))} 80 | 81 | 82 | 83 | )} 84 | 85 | 86 | ) 87 | } 88 | 89 | export default Home 90 | -------------------------------------------------------------------------------- /docusaurus/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | /** 4 | * CSS files with the .module.css suffix will be treated as CSS modules 5 | * and scoped locally. 6 | */ 7 | 8 | .heroBanner { 9 | padding: 4rem 0; 10 | text-align: center; 11 | position: relative; 12 | overflow: hidden; 13 | background-color: #f2f2f2; 14 | } 15 | 16 | @media screen and (max-width: 966px) { 17 | .heroBanner { 18 | padding: 2rem; 19 | } 20 | } 21 | 22 | .buttons { 23 | display: flex; 24 | align-items: center; 25 | justify-content: center; 26 | } 27 | 28 | .features { 29 | display: flex; 30 | align-items: center; 31 | padding: 2rem 0; 32 | width: 100%; 33 | } 34 | 35 | .featureImage { 36 | height: 150px; 37 | margin-top: 16px; 38 | margin-bottom: 24px; 39 | } 40 | -------------------------------------------------------------------------------- /docusaurus/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/.nojekyll -------------------------------------------------------------------------------- /docusaurus/static/img/Scrollable.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/Scrollable.gif -------------------------------------------------------------------------------- /docusaurus/static/img/Tooltip.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/Tooltip.gif -------------------------------------------------------------------------------- /docusaurus/static/img/area/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/area/example1.png -------------------------------------------------------------------------------- /docusaurus/static/img/area/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/area/example2.png -------------------------------------------------------------------------------- /docusaurus/static/img/box.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /docusaurus/static/img/chart/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/chart/example.png -------------------------------------------------------------------------------- /docusaurus/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/favicon.ico -------------------------------------------------------------------------------- /docusaurus/static/img/gettingstarted/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/gettingstarted/example.png -------------------------------------------------------------------------------- /docusaurus/static/img/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/home.png -------------------------------------------------------------------------------- /docusaurus/static/img/horizontalaxis/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/horizontalaxis/example1.png -------------------------------------------------------------------------------- /docusaurus/static/img/horizontalaxis/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/horizontalaxis/example2.png -------------------------------------------------------------------------------- /docusaurus/static/img/horizontalaxis/example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/horizontalaxis/example3.png -------------------------------------------------------------------------------- /docusaurus/static/img/line/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/line/example1.png -------------------------------------------------------------------------------- /docusaurus/static/img/line/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/line/example2.png -------------------------------------------------------------------------------- /docusaurus/static/img/line/example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/line/example3.png -------------------------------------------------------------------------------- /docusaurus/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docusaurus/static/img/screenshots/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/screenshots/example1.png -------------------------------------------------------------------------------- /docusaurus/static/img/screenshots/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/screenshots/example2.png -------------------------------------------------------------------------------- /docusaurus/static/img/screenshots/example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/screenshots/example3.png -------------------------------------------------------------------------------- /docusaurus/static/img/screenshots/example4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/screenshots/example4.png -------------------------------------------------------------------------------- /docusaurus/static/img/screenshots/example5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/screenshots/example5.png -------------------------------------------------------------------------------- /docusaurus/static/img/screenshots/example6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/screenshots/example6.png -------------------------------------------------------------------------------- /docusaurus/static/img/screenshots/example7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/screenshots/example7.png -------------------------------------------------------------------------------- /docusaurus/static/img/smooth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/smooth.png -------------------------------------------------------------------------------- /docusaurus/static/img/smoothing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/smoothing.png -------------------------------------------------------------------------------- /docusaurus/static/img/source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/source.png -------------------------------------------------------------------------------- /docusaurus/static/img/tooltip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/tooltip.png -------------------------------------------------------------------------------- /docusaurus/static/img/typescript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docusaurus/static/img/verticalaxis/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/verticalaxis/example1.png -------------------------------------------------------------------------------- /docusaurus/static/img/verticalaxis/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/verticalaxis/example2.png -------------------------------------------------------------------------------- /docusaurus/static/img/verticalaxis/example3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xanderdeseyn/react-native-responsive-linechart/1f2c9cdcbf69d4632dbaa2b086926760e126bff5/docusaurus/static/img/verticalaxis/example3.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-responsive-linechart", 3 | "version": "5.7.1", 4 | "author": "Xander Deseyn", 5 | "license": "MIT", 6 | "main": "lib/index.js", 7 | "types": "lib/index.d.ts", 8 | "description": "Customizable linechart for react-native that works with flex", 9 | "publishConfig": { 10 | "registry": "https://registry.npmjs.org/" 11 | }, 12 | "devDependencies": { 13 | "@babel/core": "^7.12.9", 14 | "@babel/preset-env": "^7.12.7", 15 | "@babel/preset-typescript": "^7.12.7", 16 | "@babel/runtime": "^7.12.5", 17 | "@types/jest": "^26.0.15", 18 | "@types/lodash.clamp": "^4.0.6", 19 | "@types/lodash.clonedeep": "^4.5.6", 20 | "@types/lodash.debounce": "^4.0.6", 21 | "@types/lodash.maxby": "^4.6.6", 22 | "@types/lodash.minby": "^4.6.6", 23 | "@types/react": "^17.0.0", 24 | "@types/react-native": "^0.63.37", 25 | "jest": "^26.6.3", 26 | "np": "^7.0.0", 27 | "react": "^17.0.1", 28 | "react-native": "^0.63.3", 29 | "react-native-svg": "^12.1.0", 30 | "typescript": "^4.1.2" 31 | }, 32 | "files": [ 33 | "lib/**/*" 34 | ], 35 | "keywords": [ 36 | "react-native", 37 | "chart", 38 | "flex", 39 | "responsive", 40 | "linechart" 41 | ], 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/N1ghtly/react-native-responsive-linechart" 45 | }, 46 | "peerDependencies": { 47 | "react": "*", 48 | "react-native": "*", 49 | "react-native-gesture-handler": ">=1.4.0", 50 | "react-native-svg": ">=7.0.0" 51 | }, 52 | "dependencies": { 53 | "@yr/monotone-cubic-spline": "^1.0.3", 54 | "deepmerge": "^4.2.2", 55 | "fast-deep-equal": "^3.1.3", 56 | "lodash.clamp": "^4.0.3", 57 | "lodash.clonedeep": "^4.5.0", 58 | "lodash.debounce": "^4.0.8", 59 | "lodash.maxby": "^4.6.0", 60 | "lodash.minby": "^4.6.0", 61 | "paths-js": "^0.4.11" 62 | }, 63 | "jest": { 64 | "rootDir": "./src", 65 | "testMatch": [ 66 | "**/*.spec.ts", 67 | "**/*.spec.tsx" 68 | ] 69 | }, 70 | "scripts": { 71 | "docs:deploy": "./deploy_docs.sh", 72 | "prepublish": "yarn tsc", 73 | "release": "yarn np", 74 | "test": "yarn jest" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": [] 3 | } 4 | -------------------------------------------------------------------------------- /src/Area.tsx: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge' 2 | import * as React from 'react' 3 | import { Defs, Stop, LinearGradient, Path, G } from 'react-native-svg' 4 | import ChartContext from './ChartContext' 5 | import { ChartDataPoint, Gradient, Smoothing } from './types' 6 | import { appendPointsToPath, scalePointsToDimensions, svgPath } from './utils' 7 | 8 | type Props = { 9 | /** Theme for the area */ 10 | theme?: { 11 | gradient?: Gradient 12 | } 13 | smoothing?: Smoothing 14 | /** Setting this prop will smooth out the line with bézier curves. Value between 0 and 1. */ 15 | tension?: number 16 | /** Data for the chart. Overrides optional data provided in ``. */ 17 | data?: ChartDataPoint[] 18 | } 19 | 20 | const Area: React.FC = (props) => { 21 | const { data: contextData, dimensions, viewportDomain, viewportOrigin } = React.useContext(ChartContext) 22 | const [randomGradientRef] = React.useState(Math.random().toFixed(10).toString()) 23 | 24 | const { 25 | theme: { gradient }, 26 | data = contextData, 27 | tension, 28 | smoothing, 29 | } = deepmerge(defaultProps, props) 30 | 31 | if (!dimensions) { 32 | return null 33 | } 34 | 35 | const points = scalePointsToDimensions([...data], viewportDomain, dimensions) 36 | 37 | const path = svgPath(points, smoothing, tension) 38 | 39 | const firstPoint = points[0] 40 | const lastPoint = points[points.length - 1] 41 | 42 | const closedPath = appendPointsToPath(path, [ 43 | { x: lastPoint.x, y: dimensions.height }, 44 | { x: firstPoint.x, y: dimensions.height }, 45 | ]) 46 | 47 | return ( 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ) 58 | } 59 | 60 | export { Area } 61 | 62 | const defaultProps = { 63 | theme: { 64 | gradient: { 65 | from: { 66 | color: 'red', 67 | opacity: 1, 68 | }, 69 | to: { 70 | color: 'red', 71 | opacity: 0.2, 72 | }, 73 | }, 74 | }, 75 | smoothing: 'none', 76 | tension: 0.3, 77 | } 78 | -------------------------------------------------------------------------------- /src/Axis.utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { calculateTickValues } from './Axis.utils' 2 | 3 | it('Calculating tick values for domain - simple', () => { 4 | const domain = { min: 0, max: 10 } 5 | const tickCount = 2 6 | 7 | const result = calculateTickValues(undefined, tickCount, domain) 8 | expect(result).toMatchObject([5, 10]) 9 | }) 10 | 11 | it('Calculating tick values for domain - moderate', () => { 12 | const domain = { min: -10, max: 10 } 13 | const tickCount = 2 14 | 15 | const result = calculateTickValues(undefined, tickCount, domain) 16 | expect(result).toMatchObject([0, 10]) 17 | }) 18 | 19 | it('Calculating tick values for domain - moderate 2', () => { 20 | const domain = { min: -10, max: 10 } 21 | const tickCount = 5 22 | 23 | const result = calculateTickValues(undefined, tickCount, domain) 24 | expect(result).toMatchObject([-6, -2, 2, 6, 10]) 25 | }) 26 | -------------------------------------------------------------------------------- /src/Axis.utils.ts: -------------------------------------------------------------------------------- 1 | import { AxisDomain } from './types' 2 | 3 | export const filterValuesForDomain = (values: number[], domain: AxisDomain) => { 4 | return values.filter(v => v >= domain.min && v <= domain.max) 5 | } 6 | 7 | export const calculateTickValues = ( 8 | tickValues: number[] | undefined, 9 | tickCount: number | undefined, 10 | domain: AxisDomain, 11 | includeOriginTick?: boolean 12 | ): number[] => { 13 | let ticks = tickValues 14 | 15 | const difference = Math.abs(domain.max - domain.min) 16 | 17 | const originTickOffset = includeOriginTick ? 1 : 0 18 | 19 | if (!ticks && tickCount) { 20 | ticks = new Array(tickCount) 21 | .fill(undefined) 22 | .map((v: any, i: number) => domain.min + (difference * (i + 1 - originTickOffset)) / (tickCount - originTickOffset)) 23 | } 24 | 25 | if (ticks) { 26 | return filterValuesForDomain(ticks, domain) 27 | } 28 | 29 | return [] 30 | } 31 | -------------------------------------------------------------------------------- /src/Chart.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import deepmerge from 'deepmerge' 3 | import { Animated, NativeSyntheticEvent, View, ViewStyle } from 'react-native' 4 | import { TapGestureHandler, PanGestureHandler, State, GestureHandlerRootView } from 'react-native-gesture-handler' 5 | import fastEqual from 'fast-deep-equal/react' 6 | import clamp from 'lodash.clamp' 7 | import minBy from 'lodash.minby' 8 | import maxBy from 'lodash.maxby' 9 | import debounce from 'lodash.debounce' 10 | import Svg, { G, Mask, Defs, Rect } from 'react-native-svg' 11 | import { useComponentDimensions } from './useComponentDimensions' 12 | import { AxisDomain, ChartDataPoint, Padding, ViewPort, TouchEvent, XYValue } from './types' 13 | import { ChartContextProvider } from './ChartContext' 14 | import { calculateDataDimensions, calculateViewportDomain } from './Chart.utils' 15 | import { scalePointToDimensions } from './utils' 16 | 17 | type Props = { 18 | /** All styling can be used except for padding. If you need padding, use the explicit `padding` prop below.*/ 19 | style?: ViewStyle 20 | /** Data to be used by `` or `` children. Not required, and can be overridden in Area or Line components. */ 21 | data?: ChartDataPoint[] 22 | /** Domain for the horizontal (X) axis. */ 23 | xDomain?: AxisDomain 24 | /** Domain for the vertical (Y) axis. */ 25 | yDomain?: AxisDomain 26 | /** Size of the viewport for the chart. Should always be <= the domain. */ 27 | viewport?: ViewPort 28 | /** This disables touch for the chart. You can use this if you don't need tooltips. */ 29 | disableTouch?: boolean 30 | /** This disables gestures for the chart. You can use this if you don't need scrolling in the chart. */ 31 | disableGestures?: boolean 32 | /** Padding of the chart. Use this instead of setting padding in the `style` prop. */ 33 | padding?: Padding 34 | } 35 | 36 | export type ChartHandle = { 37 | setViewportOrigin: (origin: XYValue) => void 38 | } 39 | 40 | const Chart: React.FC = React.memo( 41 | React.forwardRef((props, ref) => { 42 | const { style, children, data = [], padding, xDomain, yDomain, viewport, disableGestures, disableTouch } = deepmerge(computeDefaultProps(props), props) 43 | const { dimensions, onLayout } = useComponentDimensions() 44 | const dataDimensions = calculateDataDimensions(dimensions, padding) 45 | 46 | const tapGesture = React.createRef() // declared within constructor 47 | const panGesture = React.createRef() 48 | 49 | const [lastTouch, setLastTouch] = React.useState(undefined) 50 | const [panX, setPanX] = React.useState(viewport.initialOrigin.x) 51 | const [panY, setPanY] = React.useState(viewport.initialOrigin.y) 52 | const [offset] = React.useState(new Animated.ValueXY({ x: viewport.initialOrigin.x, y: viewport.initialOrigin.y })) 53 | 54 | const viewportDomain = calculateViewportDomain( 55 | viewport, 56 | { 57 | x: xDomain, 58 | y: yDomain, 59 | }, 60 | panX, 61 | panY 62 | ) 63 | 64 | const setViewportOrigin = (origin: XYValue) => { 65 | if (dataDimensions) { 66 | setPanX(origin.x) 67 | setPanY(origin.y) 68 | offset.x.setValue(origin.x) 69 | } 70 | } 71 | 72 | React.useImperativeHandle(ref, () => ({ setViewportOrigin })) 73 | 74 | const handleTouchEvent = React.useCallback( 75 | debounce( 76 | (x: number, y: number) => { 77 | if (dataDimensions) { 78 | setLastTouch({ 79 | position: { 80 | x: clamp(x - padding.left, 0, dataDimensions.width), 81 | y: clamp(y - padding.top, 0, dataDimensions.height), 82 | }, 83 | type: 'tap', 84 | }) 85 | } 86 | 87 | return true 88 | }, 89 | 300, 90 | { leading: true, trailing: false } 91 | ), 92 | [JSON.stringify(dataDimensions)] 93 | ) 94 | 95 | const handlePanEvent = (evt: NativeSyntheticEvent) => { 96 | if (dataDimensions) { 97 | const factorX = viewport.size.width / dataDimensions.width 98 | setPanX((offset.x as any)._value - evt.nativeEvent.translationX * factorX) 99 | 100 | const factorY = viewport.size.height / dataDimensions.height 101 | setPanY((offset.y as any)._value + evt.nativeEvent.translationY * factorY) 102 | 103 | if (evt.nativeEvent.state === State.END) { 104 | offset.x.setValue(clamp((offset.x as any)._value - evt.nativeEvent.translationX * factorX, xDomain.min, xDomain.max - viewport.size.width)) 105 | offset.y.setValue(clamp((offset.y as any)._value + evt.nativeEvent.translationY * factorY, yDomain.min, yDomain.max - viewport.size.height)) 106 | setLastTouch({ 107 | position: { 108 | x: clamp(evt.nativeEvent.x - padding.left, 0, dataDimensions.width), 109 | y: clamp(evt.nativeEvent.y - padding.top, 0, dataDimensions.height), 110 | }, 111 | translation: { 112 | x: evt.nativeEvent.translationX, 113 | y: evt.nativeEvent.translationY, 114 | }, 115 | type: 'panEnd', 116 | }) 117 | } else { 118 | setLastTouch({ 119 | position: { 120 | x: clamp(evt.nativeEvent.x - padding.left, 0, dataDimensions.width), 121 | y: clamp(evt.nativeEvent.y - padding.top, 0, dataDimensions.height), 122 | }, 123 | translation: { 124 | x: evt.nativeEvent.translationX, 125 | y: evt.nativeEvent.translationY, 126 | }, 127 | type: 'pan', 128 | }) 129 | } 130 | } 131 | return true 132 | } 133 | 134 | const _onTouchGestureEvent = Animated.event([{ nativeEvent: {} }], { 135 | useNativeDriver: true, 136 | listener: (evt) => { 137 | // Necessary to debounce function, see https://medium.com/trabe/react-syntheticevent-reuse-889cd52981b6 138 | if (evt.nativeEvent.state === State.ACTIVE) { 139 | handleTouchEvent(evt.nativeEvent.x, evt.nativeEvent.y) 140 | } 141 | }, 142 | }) 143 | 144 | const _onPanGestureEvent = Animated.event([{ nativeEvent: {} }], { 145 | useNativeDriver: true, 146 | listener: handlePanEvent, 147 | }) 148 | 149 | const childComponents = React.Children.toArray(children) 150 | // undefined because ForwardRef (Line) has name undefined 151 | const lineAndAreaComponents = childComponents.filter((c) => ['Area', undefined].includes((c as any)?.type?.name)) 152 | const otherComponents = childComponents.filter((c) => !['Area', undefined].includes((c as any)?.type?.name)) 153 | 154 | return ( 155 | 156 | 157 | {!!dimensions && ( 158 | 159 | 160 | 168 | 169 | 183 | 184 | 185 | {otherComponents} 186 | 187 | {/* Mask to fix viewport overflow bugs */} 188 | 189 | 190 | 191 | 192 | {lineAndAreaComponents} 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | )} 201 | 202 | 203 | ) 204 | }), 205 | fastEqual 206 | ) 207 | 208 | export { Chart } 209 | 210 | const computeDefaultProps = (props: Props) => { 211 | const { data = [] } = props 212 | 213 | const xDomain = props.xDomain ?? { 214 | min: data.length > 0 ? minBy(data, (d) => d.x)!.x : 0, 215 | max: data.length > 0 ? maxBy(data, (d) => d.x)!.x : 10, 216 | } 217 | 218 | const yDomain = props.yDomain ?? { 219 | min: data.length > 0 ? minBy(data, (d) => d.y)!.y : 0, 220 | max: data.length > 0 ? maxBy(data, (d) => d.y)!.y : 10, 221 | } 222 | 223 | return { 224 | padding: { 225 | left: 0, 226 | top: 0, 227 | bottom: 0, 228 | right: 0, 229 | }, 230 | xDomain, 231 | yDomain, 232 | viewport: { 233 | size: { width: Math.abs(xDomain.max - xDomain.min), height: Math.abs(yDomain.max - yDomain.min) }, 234 | initialOrigin: { x: xDomain.min, y: yDomain.min }, 235 | }, 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /src/Chart.utils.tsx: -------------------------------------------------------------------------------- 1 | import { ChartDomain, Padding, ViewPort } from './types' 2 | 3 | export const calculateDataDimensions = (dimensions: { width: number; height: number } | undefined, padding: Required) => { 4 | if (dimensions) { 5 | return { 6 | top: 0, 7 | left: 0, 8 | width: dimensions.width - padding.left - padding.right, 9 | height: dimensions.height - padding.top - padding.bottom, 10 | } 11 | } 12 | 13 | return { top: 0, left: 0, width: 10, height: 10 } 14 | } 15 | 16 | export const calculateViewportDomain = (viewport: ViewPort, domain: ChartDomain, panX: number, panY: number): ChartDomain => { 17 | const minX = Math.max(panX, domain.x.min) 18 | const maxX = Math.min(minX + viewport.size.width, domain.x.max) 19 | 20 | const minY = Math.max(panY, domain.y.min) 21 | const maxY = Math.min(minY + viewport.size.height, domain.y.max) 22 | 23 | return { 24 | x: { min: Math.min(minX, maxX - viewport.size.width), max: maxX }, 25 | y: { min: Math.min(minY, maxY - viewport.size.height), max: maxY }, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/ChartContext.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { ChartContext as TChartContext } from './types' 3 | 4 | const ChartContext = React.createContext({ 5 | data: [], 6 | dimensions: undefined, 7 | domain: { x: { min: 0, max: 0 }, y: { min: 0, max: 0 } }, 8 | viewportDomain: { x: { min: 0, max: 0 }, y: { min: 0, max: 0 } }, 9 | viewportOrigin: { x: 0, y: 0 }, 10 | viewport: { size: { width: 0, height: 0 }, initialOrigin: { x: 0, y: 0 } }, 11 | lastTouch: undefined, 12 | }) 13 | 14 | export const ChartContextProvider = ChartContext.Provider 15 | 16 | export default ChartContext 17 | -------------------------------------------------------------------------------- /src/HorizontalAxis.tsx: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge' 2 | import * as React from 'react' 3 | import { Line, Text, G } from 'react-native-svg' 4 | import ChartContext from './ChartContext' 5 | import { Stroke, Label } from './types' 6 | import { scalePointToDimensions } from './utils' 7 | import { calculateTickValues } from './Axis.utils' 8 | 9 | type Props = { 10 | theme?: { 11 | axis?: { 12 | visible?: boolean 13 | stroke?: Stroke 14 | dy?: number 15 | } 16 | ticks?: { 17 | visible?: boolean 18 | stroke?: Stroke 19 | length?: number 20 | dy?: number 21 | } 22 | labels?: { 23 | visible?: boolean 24 | label?: Label 25 | formatter?: (value: number) => string 26 | } 27 | grid?: { 28 | visible?: boolean 29 | stroke?: Stroke 30 | } 31 | } 32 | tickValues?: number[] 33 | tickCount?: number 34 | includeOriginTick?: boolean 35 | } 36 | 37 | const HorizontalAxis: React.FC = (props) => { 38 | const { 39 | theme: { axis, ticks, grid, labels }, 40 | tickValues, 41 | tickCount, 42 | includeOriginTick, 43 | } = deepmerge(defaultProps, props) 44 | 45 | const { dimensions, viewportDomain, domain } = React.useContext(ChartContext) 46 | 47 | if (!dimensions) { 48 | return null 49 | } 50 | 51 | // fround is used because of potential float comparison errors, see https://github.com/N1ghtly/react-native-responsive-linechart/issues/53 52 | const finalTickValues = calculateTickValues(tickValues, tickCount, domain.x, includeOriginTick).filter( 53 | (v) => Math.fround(v) >= Math.fround(viewportDomain.x.min) && Math.fround(v) <= Math.fround(viewportDomain.x.max) 54 | ) 55 | 56 | return ( 57 | <> 58 | {/* Render Axis */} 59 | {axis.visible && ( 60 | 0 ? axis.stroke.dashArray.join(',') : undefined} 69 | /> 70 | )} 71 | {finalTickValues.map((value) => { 72 | return ( 73 | 74 | {/* Render Grid */} 75 | {grid.visible && ( 76 | 0 ? grid.stroke.dashArray.join(',') : undefined} 86 | /> 87 | )} 88 | {/* Render Tick */} 89 | {ticks.visible && ( 90 | 100 | )} 101 | {/* Render Label */} 102 | {labels.visible && ( 103 | 107 | 116 | {labels.formatter(value)} 117 | 118 | 119 | )} 120 | 121 | ) 122 | })} 123 | > 124 | ) 125 | } 126 | 127 | export { HorizontalAxis } 128 | 129 | const defaultProps = { 130 | includeOriginTick: true, 131 | theme: { 132 | axis: { 133 | visible: true, 134 | stroke: { 135 | color: '#bbb', 136 | width: 2, 137 | opacity: 1, 138 | dashArray: [], 139 | }, 140 | dy: 0, 141 | }, 142 | grid: { 143 | visible: true, 144 | stroke: { 145 | color: '#ccc', 146 | width: 1, 147 | opacity: 1, 148 | dashArray: [], 149 | }, 150 | }, 151 | ticks: { 152 | visible: true, 153 | stroke: { 154 | color: '#000', 155 | width: 1, 156 | opacity: 1, 157 | }, 158 | dy: 0, 159 | length: 6, 160 | includeOriginTick: false, 161 | }, 162 | labels: { 163 | visible: true, 164 | label: { 165 | color: '#000', 166 | fontSize: 10, 167 | fontWeight: 300, 168 | textAnchor: 'middle', 169 | opacity: 1, 170 | dx: 0, 171 | dy: -12, 172 | rotation: 0, 173 | }, 174 | formatter: (v: number) => String(v), 175 | }, 176 | }, 177 | } 178 | -------------------------------------------------------------------------------- /src/Line.tsx: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge' 2 | import * as React from 'react' 3 | import { G, Path, Rect } from 'react-native-svg' 4 | 5 | import ChartContext from './ChartContext' 6 | import { adjustPointsForThickStroke, calculateTooltipIndex } from './Line.utils' 7 | import { ChartDataPoint, Smoothing, Stroke, Shape } from './types' 8 | import { scalePointsToDimensions, svgPath } from './utils' 9 | 10 | type Props = { 11 | /** Theme for the line */ 12 | theme?: { 13 | stroke?: Stroke 14 | scatter?: { 15 | default?: Shape 16 | selected?: Shape 17 | } 18 | } 19 | smoothing?: Smoothing 20 | /** Only works in combination with smoothing='bezier'. Value between 0 and 1. */ 21 | tension?: number 22 | /** Component to render tooltips. An example component is included: . */ 23 | tooltipComponent?: JSX.Element 24 | /** Callback method that fires when a tooltip is displayed for a data point. */ 25 | onTooltipSelect?: (value: ChartDataPoint, index: number) => void 26 | /** Callback method that fires when the user stopped touching the chart. */ 27 | onTooltipSelectEnd?: () => void 28 | /** Set to true if the tooltip should be hidden immediately when the user stops dragging the chart. */ 29 | hideTooltipOnDragEnd?: boolean 30 | /** Defines a period in ms after which the tooltip should hide */ 31 | hideTooltipAfter?: number 32 | /** Initial index for the tooltip. The tooltip will be immediately visible at this index on first render, without requiring user interaction. */ 33 | initialTooltipIndex?: number 34 | /** Data for the chart. Overrides optional data provided in ``. */ 35 | data?: ChartDataPoint[] 36 | } 37 | 38 | export type LineHandle = { 39 | setTooltipIndex: (index: number | undefined) => void 40 | } 41 | 42 | const Line = React.forwardRef(function Line(props, ref) { 43 | const { data: contextData, dimensions, viewportDomain, viewportOrigin, lastTouch } = React.useContext(ChartContext) 44 | const [tooltipIndex, setTooltipIndex] = React.useState(props.initialTooltipIndex) 45 | 46 | const { 47 | theme: { stroke, scatter }, 48 | tooltipComponent, 49 | data = contextData, 50 | tension, 51 | smoothing, 52 | onTooltipSelect, 53 | hideTooltipOnDragEnd, 54 | hideTooltipAfter, 55 | onTooltipSelectEnd = () => {}, 56 | } = deepmerge(defaultProps, props) 57 | 58 | if (!dimensions) { 59 | return null 60 | } 61 | 62 | React.useImperativeHandle(ref, () => ({ 63 | setTooltipIndex: (index: number | undefined) => { 64 | if (typeof index === 'number' && (index < 0 || index >= data.length)) { 65 | throw new Error(`Range out of bounds. Tried to set tooltip index to ${index} but there are only ${data.length} data points.`) 66 | } 67 | setTooltipIndex(index) 68 | }, 69 | })) 70 | 71 | React.useEffect(() => { 72 | if (props.initialTooltipIndex !== undefined && !lastTouch) { 73 | setTooltipIndex(props.initialTooltipIndex) 74 | } 75 | }, [props.initialTooltipIndex]) 76 | 77 | React.useEffect(() => { 78 | const scaledPoints = scalePointsToDimensions(data, viewportDomain, dimensions) 79 | const newIndex = calculateTooltipIndex(scaledPoints, lastTouch?.position) 80 | 81 | let tooltipTimer: NodeJS.Timeout 82 | 83 | if (lastTouch?.type === 'panEnd') { 84 | if (hideTooltipOnDragEnd && Math.abs(lastTouch?.translation?.x) > 5) { 85 | setTooltipIndex(undefined) 86 | } 87 | // Hide tooltip after specified time 88 | else if (typeof hideTooltipAfter === 'number') { 89 | tooltipTimer = setTimeout(() => setTooltipIndex(undefined), hideTooltipAfter) 90 | } 91 | onTooltipSelectEnd() 92 | } else if (newIndex !== tooltipIndex && lastTouch) { 93 | // Hide tooltip after specified time 94 | if (typeof hideTooltipAfter === 'number') { 95 | tooltipTimer = setTimeout(() => setTooltipIndex(undefined), hideTooltipAfter) 96 | } 97 | // Necessary for Android because pan is called even when finger is not actually panning. 98 | // If we don't check for this, we have interference with the tap handler 99 | if (lastTouch?.type !== 'pan' || Math.abs(lastTouch?.translation?.x) > 5) { 100 | setTooltipIndex(newIndex) 101 | } 102 | if (typeof onTooltipSelect === 'function' && typeof newIndex === 'number' && data.length > newIndex) { 103 | onTooltipSelect(data[newIndex], newIndex) 104 | } 105 | } else if (newIndex === tooltipIndex && lastTouch?.type === 'tap') { 106 | setTooltipIndex(undefined) 107 | } 108 | 109 | return () => { 110 | clearTimeout(tooltipTimer) 111 | } 112 | }, [lastTouch, hideTooltipAfter]) 113 | 114 | const scaledPoints = scalePointsToDimensions(data, viewportDomain, dimensions) 115 | const points = adjustPointsForThickStroke(scaledPoints, stroke) 116 | const path = svgPath(points, smoothing, tension) 117 | 118 | return ( 119 | 120 | 121 | 0 ? stroke.dashArray.join(',') : undefined} 126 | stroke={stroke.color} 127 | strokeWidth={stroke.width} 128 | strokeOpacity={stroke.opacity} 129 | mask="url(#Mask)" 130 | /> 131 | {points.map((p, i) => { 132 | const shape = i === tooltipIndex ? deepmerge(scatter.default, scatter.selected) : scatter.default 133 | // Don't render if point falls out of viewport 134 | if (data[i].x < viewportDomain.x.min || data[i].x > viewportDomain.x.max || data[i].y < viewportDomain.y.min || data[i].y > viewportDomain.y.max) { 135 | return null 136 | } 137 | // Don't render if shape has no dimensions 138 | if (shape.width === 0 || shape.height === 0) { 139 | return null 140 | } 141 | 142 | return ( 143 | 153 | ) 154 | })} 155 | 156 | {tooltipIndex !== undefined && 157 | tooltipComponent && 158 | React.cloneElement(tooltipComponent, { value: data[tooltipIndex], position: scaledPoints[tooltipIndex] })} 159 | 160 | ) 161 | }) 162 | 163 | export { Line } 164 | 165 | const defaultProps = { 166 | theme: { 167 | stroke: { 168 | color: 'black', 169 | width: 1, 170 | opacity: 1, 171 | dashArray: [], 172 | }, 173 | scatter: { 174 | default: { 175 | width: 0, 176 | height: 0, 177 | dx: 0, 178 | dy: 0, 179 | rx: 0, 180 | color: 'black', 181 | }, 182 | selected: {}, 183 | }, 184 | }, 185 | tension: 0.3, 186 | smoothing: 'none', 187 | } 188 | -------------------------------------------------------------------------------- /src/Line.utils.ts: -------------------------------------------------------------------------------- 1 | import cloneDeep from 'lodash.clonedeep' 2 | import { Stroke, XYValue } from './types' 3 | 4 | export const adjustPointsForThickStroke = (originalPoints: XYValue[], stroke: Required) => { 5 | let points = cloneDeep(originalPoints) 6 | 7 | // First and last points are adjusted to prevent "fat" lines from flowing out of the chart 8 | if (points.length >= 2) { 9 | points[0].x = points[0].x + Math.floor(stroke.width / 2) 10 | points[points.length - 1].x = points[points.length - 1].x - stroke.width / 2 11 | } 12 | 13 | return points 14 | } 15 | 16 | const smallestIndex = (arr: number[]) => { 17 | let lowest = 0 18 | for (let i = 1; i < arr.length; i++) { 19 | if (arr[i] < arr[lowest]) lowest = i 20 | } 21 | 22 | return lowest 23 | } 24 | 25 | export const calculateTooltipIndex = (points: XYValue[], lastTouch?: XYValue) => { 26 | if (!lastTouch || points.length < 1) { 27 | return undefined 28 | } 29 | 30 | return smallestIndex(points.map(p => Math.abs(p.x - lastTouch.x))) 31 | } 32 | -------------------------------------------------------------------------------- /src/Tooltip.tsx: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge' 2 | import * as React from 'react' 3 | import { Text, Rect } from 'react-native-svg' 4 | import ChartContext from './ChartContext' 5 | import { ChartDataPoint, Label, XYValue, Shape } from './types' 6 | 7 | type Props = { 8 | theme?: { 9 | label?: Label 10 | shape?: Shape 11 | formatter?: (value: ChartDataPoint) => string 12 | } 13 | value?: ChartDataPoint 14 | position?: XYValue 15 | } 16 | 17 | const Tooltip: React.FC = (props) => { 18 | const { dimensions } = React.useContext(ChartContext) 19 | 20 | const { 21 | theme: { label, formatter, shape }, 22 | value, 23 | position, 24 | } = deepmerge(defaultProps, props) 25 | 26 | if (!dimensions || !value || !position) { 27 | return null 28 | } 29 | 30 | return ( 31 | 32 | 41 | 51 | {formatter(value)} 52 | 53 | 54 | ) 55 | } 56 | 57 | export { Tooltip } 58 | 59 | const defaultProps = { 60 | theme: { 61 | label: { 62 | color: 'white', 63 | fontSize: 12, 64 | fontWeight: 700, 65 | textAnchor: 'middle', 66 | opacity: 1, 67 | dx: 0, 68 | dy: 16.5, 69 | }, 70 | shape: { 71 | width: 35, 72 | height: 20, 73 | dx: 0, 74 | dy: 20, 75 | rx: 4, 76 | color: 'black', 77 | }, 78 | formatter: (v: ChartDataPoint) => String(v.y), 79 | }, 80 | } 81 | -------------------------------------------------------------------------------- /src/VerticalAxis.tsx: -------------------------------------------------------------------------------- 1 | import deepmerge from 'deepmerge' 2 | import * as React from 'react' 3 | import { G, Line, Text } from 'react-native-svg' 4 | import ChartContext from './ChartContext' 5 | import { Label, Stroke } from './types' 6 | import { scalePointToDimensions } from './utils' 7 | import { calculateTickValues } from './Axis.utils' 8 | 9 | type Props = { 10 | theme?: { 11 | axis?: { 12 | visible?: boolean 13 | stroke?: Stroke 14 | dx?: number 15 | } 16 | ticks?: { 17 | visible?: boolean 18 | stroke?: Stroke 19 | length?: number 20 | dx?: number 21 | } 22 | labels?: { 23 | visible?: boolean 24 | label?: Label 25 | formatter?: (value: number) => string 26 | } 27 | grid?: { 28 | visible?: boolean 29 | stroke?: Stroke 30 | } 31 | } 32 | tickValues?: number[] 33 | tickCount?: number 34 | includeOriginTick?: boolean 35 | } 36 | 37 | const VerticalAxis: React.FC = (props) => { 38 | const { 39 | theme: { axis, ticks, grid, labels }, 40 | tickValues, 41 | tickCount, 42 | includeOriginTick, 43 | } = deepmerge(defaultProps, props) 44 | 45 | const { dimensions, viewportDomain, domain } = React.useContext(ChartContext) 46 | 47 | if (!dimensions) { 48 | return null 49 | } 50 | 51 | // fround is used because of potential float comparison errors, see https://github.com/N1ghtly/react-native-responsive-linechart/issues/53 52 | const finalTickValues = calculateTickValues(tickValues, tickCount, domain.y, includeOriginTick).filter( 53 | (v) => Math.fround(v) >= Math.fround(viewportDomain.y.min) && Math.fround(v) <= Math.fround(viewportDomain.y.max) 54 | ) 55 | 56 | return ( 57 | <> 58 | {/* Render Axis */} 59 | {axis.visible && ( 60 | 0 ? axis.stroke.dashArray.join(',') : undefined} 69 | /> 70 | )} 71 | {finalTickValues.map((value) => { 72 | return ( 73 | 74 | {/* Render Grid */} 75 | {grid.visible && ( 76 | 0 ? grid.stroke.dashArray.join(',') : undefined} 85 | /> 86 | )} 87 | {/* Render Tick */} 88 | {ticks.visible && ( 89 | 98 | )} 99 | {/* Render Label */} 100 | {labels.visible && ( 101 | 102 | 111 | {labels.formatter(value)} 112 | 113 | 114 | )} 115 | 116 | ) 117 | })} 118 | > 119 | ) 120 | } 121 | 122 | export { VerticalAxis } 123 | 124 | const defaultProps = { 125 | includeOriginTick: true, 126 | theme: { 127 | axis: { 128 | visible: true, 129 | stroke: { 130 | color: '#bbb', 131 | width: 2, 132 | opacity: 1, 133 | dashArray: [], 134 | }, 135 | dx: 0, 136 | }, 137 | grid: { 138 | visible: true, 139 | stroke: { 140 | color: '#ccc', 141 | width: 1, 142 | opacity: 1, 143 | dashArray: [], 144 | }, 145 | }, 146 | ticks: { 147 | visible: true, 148 | stroke: { 149 | color: '#000', 150 | width: 1, 151 | opacity: 1, 152 | }, 153 | dx: 0, 154 | length: 6, 155 | }, 156 | labels: { 157 | visible: true, 158 | label: { 159 | color: '#000', 160 | fontSize: 10, 161 | fontWeight: 300, 162 | textAnchor: 'end', 163 | opacity: 1, 164 | dx: -4, 165 | dy: 4, 166 | rotation: 0, 167 | }, 168 | formatter: (v: number) => String(v), 169 | }, 170 | }, 171 | } 172 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { Chart } from './Chart' 2 | export { HorizontalAxis } from './HorizontalAxis' 3 | export { VerticalAxis } from './VerticalAxis' 4 | export { Line } from './Line' 5 | export { Area } from './Area' 6 | export { Tooltip } from './Tooltip' 7 | export * from './types' 8 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export type XYValue = { x: number; y: number } 2 | 3 | export type ChartDataPoint = XYValue & { meta?: any } 4 | 5 | export type Padding = { top?: number; left?: number; right?: number; bottom?: number } 6 | 7 | export type Dimensions = { top: number; left: number; width: number; height: number } 8 | 9 | export type AxisDomain = { min: number; max: number } 10 | 11 | export type Smoothing = 'none' | 'cubic-spline' | 'bezier' 12 | 13 | export type ChartDomain = { x: AxisDomain; y: AxisDomain } 14 | 15 | export type Stroke = { color?: string; width?: number; opacity?: number; dashArray?: number[] } 16 | 17 | export type ViewPort = { size: { width: number; height: number }; initialOrigin: XYValue } 18 | 19 | export type Shape = { 20 | color?: string 21 | width?: number 22 | height?: number 23 | dx?: number 24 | dy?: number 25 | rx?: number 26 | opacity?: number 27 | radius?: number 28 | border?: Stroke 29 | } 30 | 31 | export type Gradient = { from?: { color?: string; opacity?: number }; to?: { color?: string; opacity?: number } } 32 | 33 | export type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 34 | 35 | export type TextAnchor = 'start' | 'middle' | 'end' 36 | 37 | export type Label = { 38 | color?: string 39 | fontSize?: number 40 | fontFamily?: string 41 | opacity?: number 42 | dy?: number 43 | dx?: number 44 | fontWeight?: FontWeight 45 | textAnchor?: TextAnchor 46 | rotation?: number 47 | } 48 | 49 | export type ChartContext = { 50 | data: ChartDataPoint[] 51 | dimensions: Dimensions | undefined 52 | domain: ChartDomain 53 | viewportDomain: ChartDomain 54 | viewportOrigin: XYValue 55 | viewport: ViewPort 56 | lastTouch: TouchEvent | undefined 57 | } 58 | 59 | export type TouchEvent = 60 | | { 61 | position: XYValue 62 | type: 'tap' 63 | } 64 | | { 65 | position: XYValue 66 | translation: XYValue 67 | type: 'pan' | 'panEnd' 68 | } 69 | -------------------------------------------------------------------------------- /src/untypedModules.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'paths-js/bezier' 2 | declare module 'paths-js/polygon' 3 | declare module '@yr/monotone-cubic-spline' 4 | declare module 'react-native-gesture-handler' 5 | -------------------------------------------------------------------------------- /src/useComponentDimensions.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { LayoutChangeEvent } from 'react-native' 3 | 4 | export const useComponentDimensions = () => { 5 | const [dimensions, setDimensions] = React.useState<{ width: number; height: number } | undefined>() 6 | 7 | const onLayout = React.useCallback((event: LayoutChangeEvent) => { 8 | const { width, height } = event.nativeEvent.layout 9 | setDimensions({ width, height }) 10 | }, []) 11 | 12 | return { dimensions, onLayout } 13 | } 14 | -------------------------------------------------------------------------------- /src/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { scalePointsToDimensions } from './utils' 2 | 3 | it('Scaling from data and domain to dimensions - simple', () => { 4 | const dimensions = { top: 0, left: 0, width: 100, height: 100 } 5 | const domain = { x: { min: 0, max: 10 }, y: { min: 0, max: 10 } } 6 | const data = [ 7 | { x: 1, y: 5 }, 8 | { x: 3, y: 8 }, 9 | ] 10 | 11 | const result = scalePointsToDimensions(data, domain, dimensions) 12 | expect(result).toMatchObject([ 13 | { 14 | x: 10, 15 | y: 50, 16 | }, 17 | { x: 30, y: 20 }, 18 | ]) 19 | }) 20 | 21 | it('Scaling from data and domain to dimensions - moderate', () => { 22 | const dimensions = { top: 20, left: 30, width: 100, height: 100 } 23 | const domain = { x: { min: -30, max: -20 }, y: { min: -50, max: 500 } } 24 | const data = [ 25 | { x: -29, y: 5 }, 26 | { x: -20, y: 500 }, 27 | ] 28 | 29 | const result = scalePointsToDimensions(data, domain, dimensions) 30 | expect(result).toMatchObject([ 31 | { x: 40, y: 110 }, 32 | { x: 130, y: 20 }, 33 | ]) 34 | }) 35 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { ChartDomain, ChartDataPoint, Dimensions, XYValue, Smoothing } from './types' 2 | import spline from '@yr/monotone-cubic-spline' 3 | import Bezier from 'paths-js/bezier' 4 | import Polygon from 'paths-js/polygon' 5 | 6 | export const formatDataForSVG = (data: ChartDataPoint[]) => { 7 | return data.map((p) => p.x + ',' + p.y).join(' ') 8 | } 9 | 10 | export const scalePointToDimensions = (data: ChartDataPoint, domain: ChartDomain, dimensions: Dimensions) => ({ 11 | x: scaleXValueToDimensions(data.x, domain, dimensions), 12 | y: scaleYValueToDimensions(data.y, domain, dimensions), 13 | }) 14 | 15 | export const scalePointsToDimensions = (data: ChartDataPoint[], domain: ChartDomain, dimensions: Dimensions) => { 16 | return data.map((p) => scalePointToDimensions(p, domain, dimensions)) 17 | } 18 | 19 | const scaleXValueToDimensions = (x: number, domain: ChartDomain, dimensions: Dimensions) => { 20 | return dimensions.left + ((x - domain.x.min) * dimensions.width) / Math.abs(domain.x.max - domain.x.min) 21 | } 22 | 23 | const scaleYValueToDimensions = (y: number, domain: ChartDomain, dimensions: Dimensions) => { 24 | return dimensions.height + dimensions.top - ((y - domain.y.min) * dimensions.height) / Math.abs(domain.y.max - domain.y.min) 25 | } 26 | 27 | export const appendPointsToPath = (path: string, points: XYValue[]) => { 28 | return `${path} ${points.map((p) => `L ${p.x} ${p.y}`).join(' ')}` 29 | } 30 | 31 | export const svgPath = (points: XYValue[], smoothing: Smoothing, tension: number) => { 32 | if (smoothing === 'bezier') { 33 | return bezierPath(points, tension) 34 | } else if (smoothing === 'cubic-spline' && points.length > 1) { 35 | return splinePath(points) 36 | } else { 37 | return linearPath(points) 38 | } 39 | } 40 | 41 | const bezierPath = (points: XYValue[], tension: number) => { 42 | return Bezier({ points: points.map((p) => [p.x, p.y]), tension }).path.print() 43 | } 44 | 45 | const splinePath = (points: XYValue[]) => { 46 | const splinePoints = spline.points(points.map((p) => [p.x, p.y])) 47 | return spline.svgPath(splinePoints) 48 | } 49 | 50 | const linearPath = (points: XYValue[]) => { 51 | return Polygon({ points: points.map((p) => [p.x, p.y]) }).path.print() 52 | } 53 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "outDir": "./lib", 7 | "jsx": "react", 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "typeRoots": ["node_modules/@types"], 12 | "skipLibCheck": true 13 | }, 14 | "include": ["src"], 15 | "exclude": ["node_modules", "**/__tests__/*"] 16 | } 17 | --------------------------------------------------------------------------------
{description}
53 | {siteConfig.tagline} 54 |