diff --git a/components/chart/area/area-chart.tsx b/components/chart/area/area-chart.tsx index d413f0f..0a0ae62 100644 --- a/components/chart/area/area-chart.tsx +++ b/components/chart/area/area-chart.tsx @@ -13,6 +13,7 @@ import { TooltipComponent } from 'echarts/components'; import * as echarts from 'echarts/core'; +import { parse, stringify } from 'zrender/lib/tool/color'; import React, { useEffect, useMemo, useRef } from 'react'; import { View } from 'react-native'; import { getAxis, valueAxisBoundsFromProps, categoryAxisBoundsFromProps } from '../axis'; @@ -39,6 +40,12 @@ echarts.use([ LineChart, ]); +const applyOpacity = (colorStr: string, opacity: number) => { + const rgba = parse(colorStr); + if (!rgba) return colorStr; + return stringify([rgba[0], rgba[1], rgba[2], opacity], 'rgba'); +}; + const ChartComponent = ({ data, width = 220, @@ -67,6 +74,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, minX, maxX, intervalX, @@ -205,7 +214,7 @@ const ChartComponent = ({ ...(xAxisLabel != null && xAxisLabel !== '' && { name: xAxisLabel, nameLocation: 'middle', - nameGap: 25, + nameGap: xAxisNameGap ?? 25, nameTextStyle: { color: theme.axis.x.tickLabelColor }, }), axisLabel: { @@ -253,7 +262,7 @@ const ChartComponent = ({ ...(yAxisLabel != null && yAxisLabel !== '' && { name: yAxisLabel, nameLocation: 'middle', - nameGap: 40, + nameGap: yAxisNameGap ?? 40, nameTextStyle: { color: theme.axis.y.tickLabelColor }, }), axisLabel: { @@ -309,11 +318,9 @@ const ChartComponent = ({ const seriesColor = theme.series[index % theme.series.length].color; const seriesLineWidth = theme.series[index]?.lineWidth ?? theme.series[0].lineWidth ?? 2; - // Convert opacity (0-1) to hex (00-FF) - const opacityHex = Math.round(areaOpacity * 255).toString(16).padStart(2, '0'); - const colorWithOpacity = seriesColor + opacityHex; - const transparentColor = seriesColor + '00'; - const solidColor = seriesColor + 'ff'; + const colorWithOpacity = applyOpacity(seriesColor, areaOpacity); + const transparentColor = applyOpacity(seriesColor, 0); + const solidColor = applyOpacity(seriesColor, 1); const areaStyleConfig = areaFill === 'gradient' @@ -451,6 +458,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, valueAxisBounds, categoryAxisBounds, ]); diff --git a/components/chart/bubble/bubble-chart.tsx b/components/chart/bubble/bubble-chart.tsx index 047514b..0df9d93 100644 --- a/components/chart/bubble/bubble-chart.tsx +++ b/components/chart/bubble/bubble-chart.tsx @@ -63,6 +63,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, minX, maxX, intervalX, @@ -172,7 +174,7 @@ const ChartComponent = ({ ...(xAxisLabel != null && xAxisLabel !== '' && { name: xAxisLabel, nameLocation: 'middle', - nameGap: 25, + nameGap: xAxisNameGap ?? 25, nameTextStyle: { color: theme.axis.x.tickLabelColor }, }), axisLabel: { @@ -211,7 +213,7 @@ const ChartComponent = ({ ...(yAxisLabel != null && yAxisLabel !== '' && { name: yAxisLabel, nameLocation: 'middle', - nameGap: 40, + nameGap: yAxisNameGap ?? 40, nameTextStyle: { color: theme.axis.y.tickLabelColor }, }), axisLabel: { @@ -336,6 +338,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, valueAxisBounds, xAxisBounds, ]); diff --git a/components/chart/candlestick/candlestick-chart.tsx b/components/chart/candlestick/candlestick-chart.tsx index 1a4e03c..7bf2eef 100644 --- a/components/chart/candlestick/candlestick-chart.tsx +++ b/components/chart/candlestick/candlestick-chart.tsx @@ -53,6 +53,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, minX, maxX, intervalX, @@ -125,7 +127,7 @@ const ChartComponent = ({ ...(xAxisLabel != null && xAxisLabel !== '' && { name: xAxisLabel, nameLocation: 'middle', - nameGap: 25, + nameGap: xAxisNameGap ?? 25, nameTextStyle: { color: theme.axis.x.tickLabelColor }, }), axisLabel: { @@ -161,7 +163,7 @@ const ChartComponent = ({ ...(yAxisLabel != null && yAxisLabel !== '' && { name: yAxisLabel, nameLocation: 'middle', - nameGap: 40, + nameGap: yAxisNameGap ?? 40, nameTextStyle: { color: theme.axis.y.tickLabelColor }, }), axisLabel: { @@ -316,6 +318,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, minX, maxX, intervalX, diff --git a/components/chart/column/column-chart.tsx b/components/chart/column/column-chart.tsx index 7a68ba5..111f502 100644 --- a/components/chart/column/column-chart.tsx +++ b/components/chart/column/column-chart.tsx @@ -74,6 +74,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, minX, maxX, intervalX, @@ -233,6 +235,7 @@ const ChartComponent = ({ const categoryTickFormatter = horizontal ? yAxisTickLabelFormatter : xAxisTickLabelFormatter; const categoryAxisTheme = horizontal ? theme.axis.y : theme.axis.x; const categoryAxisTitle = horizontal ? yAxisLabel : xAxisLabel; + const categoryAxisNameGap = horizontal ? yAxisNameGap : xAxisNameGap; const valueShow = horizontal ? showXAxis : showYAxis; const valueShowTicks = horizontal ? showXAxisTicks : showYAxisTicks; @@ -240,6 +243,7 @@ const ChartComponent = ({ const valueTickFormatter = horizontal ? xAxisTickLabelFormatter : yAxisTickLabelFormatter; const valueAxisTheme = horizontal ? theme.axis.x : theme.axis.y; const valueAxisTitle = horizontal ? xAxisLabel : yAxisLabel; + const valueAxisNameGap = horizontal ? xAxisNameGap : yAxisNameGap; const categoryAxisConfig: any = { type: 'category', @@ -250,7 +254,7 @@ const ChartComponent = ({ ...(categoryAxisTitle != null && categoryAxisTitle !== '' && { name: categoryAxisTitle, nameLocation: 'middle', - nameGap: 25, + nameGap: categoryAxisNameGap ?? 25, nameTextStyle: { color: categoryAxisTheme.tickLabelColor }, }), axisLabel: { @@ -299,7 +303,7 @@ const ChartComponent = ({ ...(valueAxisTitle != null && valueAxisTitle !== '' && { name: valueAxisTitle, nameLocation: 'middle', - nameGap: 40, + nameGap: valueAxisNameGap ?? 40, nameTextStyle: { color: valueAxisTheme.tickLabelColor }, }), axisLabel: { @@ -619,6 +623,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, categoryAxisData, valueAxisBounds, categoryAxisBounds, diff --git a/components/chart/props/cartesian.ts b/components/chart/props/cartesian.ts index eb6e3d9..6b3f98a 100644 --- a/components/chart/props/cartesian.ts +++ b/components/chart/props/cartesian.ts @@ -112,6 +112,16 @@ export interface CartesianChartProps extends CommonChartProps { * @default undefined */ yAxisLabel?: string; + /** + * Distance (px) between the X-axis caption ({@link xAxisLabel}) and the axis line/labels. + * @default 25 (category axis); 40 (value axis) + */ + xAxisNameGap?: number; + /** + * Distance (px) between the Y-axis caption ({@link yAxisLabel}) and the axis line/labels. + * @default 25 (category axis); 40 (value axis) + */ + yAxisNameGap?: number; /** * Grid positioning configuration. */ diff --git a/components/chart/scatter/scatter-chart.tsx b/components/chart/scatter/scatter-chart.tsx index 1d633f3..e4a704c 100644 --- a/components/chart/scatter/scatter-chart.tsx +++ b/components/chart/scatter/scatter-chart.tsx @@ -74,6 +74,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, minX, maxX, intervalX, @@ -171,7 +173,7 @@ const ChartComponent = ({ ...(xAxisLabel != null && xAxisLabel !== '' && { name: xAxisLabel, nameLocation: 'middle', - nameGap: 25, + nameGap: xAxisNameGap ?? 25, nameTextStyle: { color: theme.axis.x.tickLabelColor }, }), axisLabel: { @@ -213,7 +215,7 @@ const ChartComponent = ({ ...(yAxisLabel != null && yAxisLabel !== '' && { name: yAxisLabel, nameLocation: 'middle', - nameGap: 40, + nameGap: yAxisNameGap ?? 40, nameTextStyle: { color: theme.axis.y.tickLabelColor }, }), axisLabel: { @@ -355,6 +357,8 @@ const ChartComponent = ({ yAxisTickLabelFormatter, xAxisLabel, yAxisLabel, + xAxisNameGap, + yAxisNameGap, valueAxisBounds, categoryAxisBounds, ]); diff --git a/package-lock.json b/package-lock.json index 284921d..8787c7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@wavemaker/react-native-echarts", - "version": "1.0.3", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@wavemaker/react-native-echarts", - "version": "1.0.3", + "version": "1.0.5", "license": "MIT", "dependencies": { "@wuba/react-native-echarts": "^3.0.1", diff --git a/package.json b/package.json index 0b6b558..0e18929 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "data-visualization", "data-analysis" ], - "version": "1.0.3", + "version": "1.0.5", "scripts": { "start": "expo start", "reset-project": "node ./scripts/reset-project.js", @@ -33,6 +33,7 @@ "web": "expo start --web", "lint": "expo lint", "storybook": "storybook dev -p 6006", + "storybook:clean": "rm -rf node_modules/.cache/storybook node_modules/.vite && storybook dev -p 6006", "build-storybook": "storybook build", "generate:wmx": "node ./scripts/generate-wmx.js", "build:lib": "node ./scripts/build-lib.js", diff --git a/stories/area/x-axis/area.x-axis.stories.tsx b/stories/area/x-axis/area.x-axis.stories.tsx index 3de967f..71803e3 100644 --- a/stories/area/x-axis/area.x-axis.stories.tsx +++ b/stories/area/x-axis/area.x-axis.stories.tsx @@ -64,6 +64,15 @@ export const XAxisLabel: Story = { }, }; +/** xAxisNameGap — extra distance (px) between the X-axis label and the axis line. */ +export const XAxisNameGap: Story = { + args: { + data, + xAxisLabel: 'Month', + xAxisNameGap: 45, + }, +}; + /** minX and maxX — fixed X-axis extent (category index; six points → narrow window). */ export const FixedMinMax: Story = { args: { diff --git a/stories/area/y-axis/area.y-axis.stories.tsx b/stories/area/y-axis/area.y-axis.stories.tsx index 2e2058f..dd3e9d6 100644 --- a/stories/area/y-axis/area.y-axis.stories.tsx +++ b/stories/area/y-axis/area.y-axis.stories.tsx @@ -45,6 +45,15 @@ export const YAxisLabel: Story = { }, }; +/** yAxisNameGap — extra distance (px) between the Y-axis label and the axis line. */ +export const YAxisNameGap: Story = { + args: { + data, + yAxisLabel: 'Revenue ($)', + yAxisNameGap: 55, + }, +}; + /** minY and maxY — fixed value-axis bounds (non-zero min, headroom above the series). */ export const FixedMinMax: Story = { args: { diff --git a/stories/bar/x-axis/bar.x-axis.stories.tsx b/stories/bar/x-axis/bar.x-axis.stories.tsx index 9a1a9bb..026a5a3 100644 --- a/stories/bar/x-axis/bar.x-axis.stories.tsx +++ b/stories/bar/x-axis/bar.x-axis.stories.tsx @@ -50,6 +50,15 @@ export const XAxisLabel: Story = { }, }; +/** xAxisNameGap — extra distance (px) between the X-axis label and the axis line. */ +export const XAxisNameGap: Story = { + args: { + data, + xAxisLabel: 'Count', + xAxisNameGap: 45, + }, +}; + /** minX and maxX — fixed value scale along X (bar length) with non-zero min. */ export const FixedMinMax: Story = { args: { diff --git a/stories/bar/y-axis/bar.y-axis.stories.tsx b/stories/bar/y-axis/bar.y-axis.stories.tsx index 995b266..bdb7494 100644 --- a/stories/bar/y-axis/bar.y-axis.stories.tsx +++ b/stories/bar/y-axis/bar.y-axis.stories.tsx @@ -52,6 +52,15 @@ export const YAxisLabel: Story = { }, }; +/** yAxisNameGap — extra distance (px) between the Y-axis label and the axis line. */ +export const YAxisNameGap: Story = { + args: { + data, + yAxisLabel: 'Category', + yAxisNameGap: 55, + }, +}; + /** minY and maxY — fixed category extent (horizontal bar: category index along Y). */ export const FixedMinMax: Story = { args: { diff --git a/stories/bubble/x-axis/bubble.x-axis.stories.tsx b/stories/bubble/x-axis/bubble.x-axis.stories.tsx index aa56799..1f0c59b 100644 --- a/stories/bubble/x-axis/bubble.x-axis.stories.tsx +++ b/stories/bubble/x-axis/bubble.x-axis.stories.tsx @@ -64,6 +64,15 @@ export const XAxisLabel: Story = { }, }; +/** xAxisNameGap — extra distance (px) between the X-axis label and the axis line. */ +export const XAxisNameGap: Story = { + args: { + data, + xAxisLabel: 'X', + xAxisNameGap: 45, + }, +}; + /** minX and maxX — fixed numeric X scale (non-zero min; bubble X ≈ 10–30). */ export const FixedMinMax: Story = { args: { diff --git a/stories/bubble/y-axis/bubble.y-axis.stories.tsx b/stories/bubble/y-axis/bubble.y-axis.stories.tsx index aaada64..78e21b4 100644 --- a/stories/bubble/y-axis/bubble.y-axis.stories.tsx +++ b/stories/bubble/y-axis/bubble.y-axis.stories.tsx @@ -59,6 +59,15 @@ export const YAxisLabel: Story = { }, }; +/** yAxisNameGap — extra distance (px) between the Y-axis label and the axis line. */ +export const YAxisNameGap: Story = { + args: { + data, + yAxisLabel: 'Y', + yAxisNameGap: 55, + }, +}; + /** minY and maxY — fixed Y range with non-zero floor (bubble Y is about 15–30). */ export const FixedMinMax: Story = { args: { diff --git a/stories/candlestick/x-axis/candlestick.x-axis.stories.tsx b/stories/candlestick/x-axis/candlestick.x-axis.stories.tsx index c3da151..471730b 100644 --- a/stories/candlestick/x-axis/candlestick.x-axis.stories.tsx +++ b/stories/candlestick/x-axis/candlestick.x-axis.stories.tsx @@ -58,6 +58,16 @@ export const XAxisLabel: Story = { }, }; +/** xAxisNameGap — extra distance (px) between the X-axis label and the axis line. */ +export const XAxisNameGap: Story = { + args: { + data, + xAxisData, + xAxisLabel: 'Day', + xAxisNameGap: 45, + }, +}; + /** minX and maxX — fixed category window (five sessions → indices 1–3). */ export const FixedMinMax: Story = { args: { diff --git a/stories/candlestick/y-axis/candlestick.y-axis.stories.tsx b/stories/candlestick/y-axis/candlestick.y-axis.stories.tsx index cc0adfc..d9984fe 100644 --- a/stories/candlestick/y-axis/candlestick.y-axis.stories.tsx +++ b/stories/candlestick/y-axis/candlestick.y-axis.stories.tsx @@ -51,6 +51,16 @@ export const YAxisLabel: Story = { }, }; +/** yAxisNameGap — extra distance (px) between the Y-axis label and the axis line. */ +export const YAxisNameGap: Story = { + args: { + data, + xAxisData, + yAxisLabel: 'Price ($)', + yAxisNameGap: 55, + }, +}; + /** minY and maxY — fixed price axis with non-zero floor and padding below lows / above highs. */ export const FixedMinMax: Story = { args: { diff --git a/stories/column/x-axis/column.x-axis.stories.tsx b/stories/column/x-axis/column.x-axis.stories.tsx index 5b4153f..e93dc3a 100644 --- a/stories/column/x-axis/column.x-axis.stories.tsx +++ b/stories/column/x-axis/column.x-axis.stories.tsx @@ -57,6 +57,15 @@ export const XAxisLabel: Story = { }, }; +/** xAxisNameGap — extra distance (px) between the X-axis label and the axis line. */ +export const XAxisNameGap: Story = { + args: { + data, + xAxisLabel: 'Month', + xAxisNameGap: 45, + }, +}; + /** minX and maxX — fixed X-axis extent (category index; six points → narrow window). */ export const FixedMinMax: Story = { args: { diff --git a/stories/column/y-axis/column.y-axis.stories.tsx b/stories/column/y-axis/column.y-axis.stories.tsx index 9a60842..c5aa4c8 100644 --- a/stories/column/y-axis/column.y-axis.stories.tsx +++ b/stories/column/y-axis/column.y-axis.stories.tsx @@ -45,6 +45,15 @@ export const YAxisLabel: Story = { }, }; +/** yAxisNameGap — extra distance (px) between the Y-axis label and the axis line. */ +export const YAxisNameGap: Story = { + args: { + data, + yAxisLabel: 'Value', + yAxisNameGap: 55, + }, +}; + /** minY and maxY — fixed value-axis bounds (non-zero min, headroom above the bars). */ export const FixedMinMax: Story = { args: { diff --git a/stories/line/x-axis/line.x-axis.stories.tsx b/stories/line/x-axis/line.x-axis.stories.tsx index 5c4108d..ef568e7 100644 --- a/stories/line/x-axis/line.x-axis.stories.tsx +++ b/stories/line/x-axis/line.x-axis.stories.tsx @@ -47,6 +47,15 @@ export const XAxisLabel: Story = { }, }; +/** xAxisNameGap — extra distance (px) between the X-axis label and the axis line. */ +export const XAxisNameGap: Story = { + args: { + data, + xAxisLabel: 'Month', + xAxisNameGap: 45, + }, +}; + /** minX and maxX — fixed X-axis extent (category index; six points → narrow window). */ export const FixedMinMax: Story = { args: { diff --git a/stories/line/y-axis/line.y-axis.stories.tsx b/stories/line/y-axis/line.y-axis.stories.tsx index f793af9..09d016c 100644 --- a/stories/line/y-axis/line.y-axis.stories.tsx +++ b/stories/line/y-axis/line.y-axis.stories.tsx @@ -42,6 +42,15 @@ export const YAxisLabel: Story = { }, }; +/** yAxisNameGap — extra distance (px) between the Y-axis label and the axis line. */ +export const YAxisNameGap: Story = { + args: { + data, + yAxisLabel: 'Amount', + yAxisNameGap: 55, + }, +}; + /** minY and maxY — fixed value-axis bounds (non-zero min, headroom above the series). */ export const FixedMinMax: Story = { args: { diff --git a/stories/scatter/x-axis/scatter.x-axis.stories.tsx b/stories/scatter/x-axis/scatter.x-axis.stories.tsx index 1e5b03b..d73ef1b 100644 --- a/stories/scatter/x-axis/scatter.x-axis.stories.tsx +++ b/stories/scatter/x-axis/scatter.x-axis.stories.tsx @@ -58,6 +58,15 @@ export const XAxisLabel: Story = { }, }; +/** xAxisNameGap — extra distance (px) between the X-axis label and the axis line. */ +export const XAxisNameGap: Story = { + args: { + data, + xAxisLabel: 'X value', + xAxisNameGap: 45, + }, +}; + /** minX and maxX — fixed X-axis extent (category index; non-zero min). */ export const FixedMinMax: Story = { args: { diff --git a/stories/scatter/y-axis/scatter.y-axis.stories.tsx b/stories/scatter/y-axis/scatter.y-axis.stories.tsx index d199229..e086cb2 100644 --- a/stories/scatter/y-axis/scatter.y-axis.stories.tsx +++ b/stories/scatter/y-axis/scatter.y-axis.stories.tsx @@ -53,6 +53,15 @@ export const YAxisLabel: Story = { }, }; +/** yAxisNameGap — extra distance (px) between the Y-axis label and the axis line. */ +export const YAxisNameGap: Story = { + args: { + data, + yAxisLabel: 'Y value', + yAxisNameGap: 55, + }, +}; + /** minY and maxY — fixed Y range with non-zero floor (series Y is about 5–12). */ export const FixedMinMax: Story = { args: {