From 15bc03d18fac347feb2e0e5cef4ac529174fbefb Mon Sep 17 00:00:00 2001 From: berman Date: Sat, 25 Apr 2026 23:01:35 -0400 Subject: [PATCH] chore: revive maintenance release --- .github/workflows/ci.yml | 26 ++++++++ App.js | 4 +- CHANGELOG.md | 9 +++ contributing.md | 28 ++++++-- index.js | 10 +-- package.json | 12 ++-- src/AbstractChart.tsx | 36 +++++++---- src/BarChart.tsx | 68 ++++++++++---------- src/PieChart.tsx | 2 +- src/ProgressChart.tsx | 10 +-- src/StackedBarChart.tsx | 8 +-- src/contribution-graph/ContributionGraph.tsx | 22 +++++-- src/contribution-graph/index.tsx | 2 +- src/line-chart/LineChart.tsx | 50 +++++++------- tsconfig.json | 1 + 15 files changed, 189 insertions(+), 99 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..cebdb659 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: + pull_request: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + run: npm install --legacy-peer-deps --ignore-scripts + + - name: Build + run: npm run build diff --git a/App.js b/App.js index 8c31b6d5..3311788b 100644 --- a/App.js +++ b/App.js @@ -113,7 +113,7 @@ export default class App extends React.Component { const height = 256; return ( - {chartConfigs.map(chartConfig => { + {chartConfigs.map((chartConfig, index) => { const labelStyle = { color: chartConfig.color(), marginVertical: 10, @@ -126,7 +126,7 @@ export default class App extends React.Component { }; return ( / +``` + +Use these branch types: + +- `fix/` for user-visible bug fixes +- `feat/` for new public functionality +- `docs/` for documentation-only changes +- `ci/` for automation and CI changes +- `chore/` for maintenance, release hygiene, and dependency upkeep +- `refactor/` for internal changes that do not intentionally change behavior +- `release/` for version bump and publishing prep + +Include an issue number when the branch maps to a specific issue, for example `fix/733-svg-gradient-ids`. Keep each branch scoped to one pull request. + ## Workflow First clone: @@ -11,16 +31,16 @@ First clone: ```sh git clone git@github.com:indiespirit/react-native-chart-kit.git cd react-native-chart-kit -yarn install +npm install --legacy-peer-deps ``` -In order to run it, you are gonna have to flip values for "main" and "_main" in package json. This is nessesary because both npm and expo have a notion of a main file, but for npm it's the file that you run when you import this library in your app; and for expo it's the file that it uses to display the example app. +In order to run it, you are gonna have to flip values for "main" and "\_main" in package json. This is nessesary because both npm and expo have a notion of a main file, but for npm it's the file that you run when you import this library in your app; and for expo it's the file that it uses to display the example app. Don't forget to flip it back before commiting. **After you update fix the package.json** ```sh -yarn start # And get you expo app ready on your phone +npm start # And get your Expo app ready on your phone +npm run build # Verify the package build ``` - diff --git a/index.js b/index.js index 038a99ce..9c17fed8 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,10 @@ -import AbstractChart from "./src/abstract-chart"; +import AbstractChart from "./src/AbstractChart"; import LineChart from "./src/line-chart"; -import BarChart from "./src/bar-chart"; -import PieChart from "./src/pie-chart"; -import ProgressChart from "./src/progress-chart"; +import BarChart from "./src/BarChart"; +import PieChart from "./src/PieChart"; +import ProgressChart from "./src/ProgressChart"; import ContributionGraph from "./src/contribution-graph"; -import StackedBarChart from "./src/stackedbar-chart"; +import StackedBarChart from "./src/StackedBarChart"; export { AbstractChart, diff --git a/package.json b/package.json index 9501f9f1..de52ebe3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "name": "react-native-chart-kit", - "version": "6.11.0", + "version": "6.12.1", "devDependencies": { + "@types/react": "16.14.8", "@types/react-native": "^0.62.13", "babel-eslint": "10.x", "babel-plugin-module-resolver": "^3.1.1", @@ -24,7 +25,7 @@ "react-native-scrollable-tab-view": "^1.0.0", "react-native-svg": "11.0.1", "react-test-renderer": "16.7.0", - "typescript": "^3.9.5" + "typescript": "^5.4.5" }, "_main": "./node_modules/expo/AppEntry.js", "main": "./dist/index.js", @@ -38,10 +39,10 @@ "android": "expo start --android", "ios": "expo start --ios", "test": "jest", + "typecheck": "tsc --noEmit", "build": "tsc", "dev": "tsc --watch", - "prepublish": "yarn build", - "prepare": "yarn build" + "prepare": "npm run build" }, "jest": { "preset": "jest-expo" @@ -67,6 +68,9 @@ "type": "git", "url": "https://github.com/indiespirit/react-native-chart-kit" }, + "overrides": { + "@types/react": "16.14.8" + }, "resolutions": { "@types/react": "16.14.8" } diff --git a/src/AbstractChart.tsx b/src/AbstractChart.tsx index 4f7b124f..5facb526 100644 --- a/src/AbstractChart.tsx +++ b/src/AbstractChart.tsx @@ -38,13 +38,27 @@ export type AbstractChartState = {}; export const DEFAULT_X_LABELS_HEIGHT_PERCENTAGE = 0.75; +let nextChartId = 0; + class AbstractChart< IProps extends AbstractChartProps, IState extends AbstractChartState > extends Component { + private chartId = nextChartId++; + + protected getGradientId = (id: string) => { + return `chart-kit-${this.chartId}-${id}`; + }; + + protected getGradientUrl = (id: string) => { + return `url(#${this.getGradientId(id)})`; + }; + calcScaler = (data: number[]) => { if (this.props.fromZero && this.props.fromNumber) { - return Math.max(...data, this.props.fromNumber) - Math.min(...data, 0) || 1; + return ( + Math.max(...data, this.props.fromNumber) - Math.min(...data, 0) || 1 + ); } else if (this.props.fromZero) { return Math.max(...data, 0) - Math.min(...data, 0) || 1; } else if (this.props.fromNumber) { @@ -148,7 +162,7 @@ class AbstractChart< const y = (basePosition / count) * i + paddingTop; return ( { return ( ) => ( - {useShadowColorFromDataset ? ( + {useShadowColorFromDataset && data ? ( data.map((dataset, index) => ( { const barWidth = 32 * this.getBarPercentage(); return ( { height={(Math.abs(barHeight) / 4) * 3} fill={ withCustomBarColorFromData - ? `url(#customColor_0_${i})` - : "url(#fillShadowGradientFrom)" + ? this.getGradientUrl(`customColor_0_${i}`) + : this.getGradientUrl("fillShadowGradientFrom") } /> ); @@ -121,7 +120,7 @@ class BarChart extends AbstractChart { const barWidth = 32 * this.getBarPercentage(); return ( { return ( { {flatColor ? ( ) : ( - - )} + + )} ); })} @@ -185,24 +184,23 @@ class BarChart extends AbstractChart { const baseHeight = this.calcBaseHeight(data, height); const renderLabel = (value: number) => { - if(this.props.chartConfig.formatTopBarValue) { - return this.props.chartConfig.formatTopBarValue(value) + if (this.props.chartConfig.formatTopBarValue) { + return this.props.chartConfig.formatTopBarValue(value); } - else { - return value - } - } + + return value; + }; + return data.map((x, i) => { const barHeight = this.calcHeight(x, data, height); const barWidth = 32 * this.getBarPercentage(); return ( { (this.props.chartConfig && this.props.chartConfig.decimalPlaces) ?? 2, formatYLabel: (this.props.chartConfig && this.props.chartConfig.formatYLabel) || - function (label) { + function(label) { return label; }, formatXLabel: (this.props.chartConfig && this.props.chartConfig.formatXLabel) || - function (label) { + function(label) { return label; } }; @@ -273,37 +271,37 @@ class BarChart extends AbstractChart { height={height} rx={borderRadius} ry={borderRadius} - fill="url(#backgroundGradient)" + fill={this.getGradientUrl("backgroundGradient")} /> {withInnerLines ? this.renderHorizontalLines({ - ...config, - count: segments, - paddingTop - }) + ...config, + count: segments, + paddingTop + }) : null} {withHorizontalLabels ? this.renderHorizontalLabels({ - ...config, - count: segments, - data: data.datasets[0].data, - paddingTop: paddingTop as number, - paddingRight: paddingRight as number - }) + ...config, + count: segments, + data: data.datasets[0].data, + paddingTop: paddingTop as number, + paddingRight: paddingRight as number + }) : null} {withVerticalLabels ? this.renderVerticalLabels({ - ...config, - labels: data.labels, - paddingRight: paddingRight as number, - paddingTop: paddingTop as number, - horizontalOffset: barWidth * this.getBarPercentage() - }) + ...config, + labels: data.labels, + paddingRight: paddingRight as number, + paddingTop: paddingTop as number, + horizontalOffset: barWidth * this.getBarPercentage() + }) : null} diff --git a/src/PieChart.tsx b/src/PieChart.tsx index 3e498ddc..d8316e69 100644 --- a/src/PieChart.tsx +++ b/src/PieChart.tsx @@ -69,7 +69,7 @@ class PieChart extends AbstractChart { } return ( - + {hasLegend ? ( { return ( { return ( { return ( { return ( 15 ? y + 15 : y + 7} @@ -164,7 +164,7 @@ class StackedBarChart extends AbstractChart< }) => legend.map((x, i) => { return ( - + {this.renderHorizontalLines({ diff --git a/src/contribution-graph/ContributionGraph.tsx b/src/contribution-graph/ContributionGraph.tsx index 62f7d742..54a44b98 100644 --- a/src/contribution-graph/ContributionGraph.tsx +++ b/src/contribution-graph/ContributionGraph.tsx @@ -48,9 +48,21 @@ class ContributionGraph extends AbstractChart< }; } - UNSAFE_componentWillReceiveProps(nextProps: ContributionGraphProps) { + componentDidUpdate(prevProps: ContributionGraphProps) { + const shouldUpdateValueCache = + prevProps.values !== this.props.values || + prevProps.endDate !== this.props.endDate || + prevProps.numDays !== this.props.numDays || + prevProps.accessor !== this.props.accessor || + prevProps.titleForValue !== this.props.titleForValue || + prevProps.tooltipDataAttrs !== this.props.tooltipDataAttrs; + + if (!shouldUpdateValueCache) { + return; + } + let { maxValue, minValue, valueCache } = this.getValueCache( - nextProps.values + this.props.values ); this.setState({ @@ -166,7 +178,9 @@ class ContributionGraph extends AbstractChart< if (count) { const opacity = mapValue( count, - this.state.maxValue === this.state.minValue ? 0: this.state.minValue, + this.state.maxValue === this.state.minValue + ? 0 + : this.state.minValue, isNaN(this.state.maxValue) ? 1 : this.state.maxValue, 0.15 + 0.05, // + 0.05 to make smaller values a bit more visible 1 @@ -387,7 +401,7 @@ class ContributionGraph extends AbstractChart< height={this.props.height} rx={borderRadius} ry={borderRadius} - fill="url(#backgroundGradient)" + fill={this.getGradientUrl("backgroundGradient")} /> {this.renderMonthLabels()} {this.renderAllWeeks()} diff --git a/src/contribution-graph/index.tsx b/src/contribution-graph/index.tsx index afa9d027..35e4386b 100644 --- a/src/contribution-graph/index.tsx +++ b/src/contribution-graph/index.tsx @@ -19,7 +19,7 @@ export interface ContributionGraphProps extends AbstractChartProps { showOutOfRangeDays?: boolean; accessor?: string; getMonthLabel?: (monthIndex: number) => string; - onDayPress?: ({ count: number, date: Date }) => void; + onDayPress?: (value: { count: number; date: Date }) => void; classForValue?: (value: string) => string; style?: Partial; titleForValue?: (value: ContributionChartValue) => string; diff --git a/src/line-chart/LineChart.tsx b/src/line-chart/LineChart.tsx index 895e911a..cea103a4 100644 --- a/src/line-chart/LineChart.tsx +++ b/src/line-chart/LineChart.tsx @@ -279,7 +279,7 @@ class LineChart extends AbstractChart { } } = this.props; const xMax = this.getXMaxValues(data); - data.forEach(dataset => { + data.forEach((dataset, datasetIndex) => { if (dataset.withDots == false) return; dataset.data.forEach((x, i) => { @@ -310,7 +310,7 @@ class LineChart extends AbstractChart { output.push( { {...this.getPropsForDots(x, i)} />, { fillOpacity={0} onPress={onPress} />, - renderDotContent({ x: cx, y: cy, index: i, indexData: x }) + + {renderDotContent({ x: cx, y: cy, index: i, indexData: x })} + ); }); }); @@ -431,7 +433,7 @@ class LineChart extends AbstractChart { lastIndex = index; }); - data.forEach(dataset => { + data.forEach((dataset, datasetIndex) => { if (dataset.withScrollableDot == false) return; const perData = width / dataset.data.length; @@ -491,9 +493,9 @@ class LineChart extends AbstractChart { extrapolate: "clamp" }); - output.push([ + output.push( { /> , { strokeWidth={scrollableDotStrokeWidth} fill={scrollableDotFill} /> - ]); + ); }); return output; @@ -583,9 +585,9 @@ class LineChart extends AbstractChart { (dataset.data.length - 1)},${(height / 4) * 3 + paddingTop} ${paddingRight},${(height / 4) * 3 + paddingTop}` } - fill={`url(#fillShadowGradientFrom${ - useColorFromDataset ? `_${index}` : "" - })`} + fill={this.getGradientUrl( + `fillShadowGradientFrom${useColorFromDataset ? `_${index}` : ""}` + )} strokeWidth={0} /> ); @@ -766,9 +768,9 @@ class LineChart extends AbstractChart { ); @@ -779,7 +781,7 @@ class LineChart extends AbstractChart { const baseLegendItemX = width / (legend.length + 1); return legend.map((legendItem, i) => ( - + { height={height + legendOffset} rx={borderRadius} ry={borderRadius} - fill="url(#backgroundGradient)" + fill={this.getGradientUrl("backgroundGradient")} fillOpacity={transparent ? 0 : 1} /> {this.props.data.legend && @@ -981,13 +983,15 @@ class LineChart extends AbstractChart { contentContainerStyle={{ width: width * 2 }} showsHorizontalScrollIndicator={false} scrollEventThrottle={16} - onScroll={Animated.event([ - { - nativeEvent: { - contentOffset: { x: scrollableDotHorizontalOffset } + onScroll={Animated.event( + [ + { + nativeEvent: { + contentOffset: { x: scrollableDotHorizontalOffset } + } } - } - ], { useNativeDriver: false } + ], + { useNativeDriver: false } )} horizontal bounces={false} diff --git a/tsconfig.json b/tsconfig.json index 07904ad0..9a340193 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,7 @@ "inlineSourceMap": true, "inlineSources": true, "esModuleInterop": true, + "skipLibCheck": true, "noErrorTruncation": true, "jsx": "react-native" }