diff --git a/src/plugins/d3/__stories__/BarX.stories.tsx b/src/plugins/d3/__stories__/bar-x/BarX.stories.tsx
similarity index 86%
rename from src/plugins/d3/__stories__/BarX.stories.tsx
rename to src/plugins/d3/__stories__/bar-x/BarX.stories.tsx
index dc28cfdc..91098eea 100644
--- a/src/plugins/d3/__stories__/BarX.stories.tsx
+++ b/src/plugins/d3/__stories__/bar-x/BarX.stories.tsx
@@ -2,15 +2,15 @@ import React from 'react';
import {StoryObj} from '@storybook/react';
import {withKnobs} from '@storybook/addon-knobs';
import {Button} from '@gravity-ui/uikit';
-import {settings} from '../../../libs';
-import {D3Plugin} from '..';
+import {settings} from '../../../../libs';
+import {D3Plugin} from '../..';
import {
BasicBarXChart,
BasicLinearBarXChart,
BasicDateTimeBarXChart,
-} from '../examples/bar-x/Basic';
-import {GroupedColumns} from '../examples/bar-x/GroupedColumns';
-import {StackedColumns} from '../examples/bar-x/StackedColumns';
+} from '../../examples/bar-x/Basic';
+import {GroupedColumns} from '../../examples/bar-x/GroupedColumns';
+import {StackedColumns} from '../../examples/bar-x/StackedColumns';
const ChartStory = ({Chart}: {Chart: React.FC}) => {
const [shown, setShown] = React.useState(false);
diff --git a/src/plugins/d3/__stories__/bar-x/Playground.stories.tsx b/src/plugins/d3/__stories__/bar-x/Playground.stories.tsx
new file mode 100644
index 00000000..660e89f2
--- /dev/null
+++ b/src/plugins/d3/__stories__/bar-x/Playground.stories.tsx
@@ -0,0 +1,78 @@
+import React from 'react';
+import {StoryObj} from '@storybook/react';
+import {Button} from '@gravity-ui/uikit';
+import {settings} from '../../../../libs';
+import {D3Plugin} from '../..';
+import {ChartKitWidgetData} from '../../../../types';
+import {ChartKit} from '../../../../components/ChartKit';
+import {groups} from 'd3';
+import nintendoGames from '../../examples/nintendoGames';
+
+function prepareData(): ChartKitWidgetData {
+ const gamesByPlatform = groups(nintendoGames, (item) => item['platform']);
+ const data = gamesByPlatform.map(([value, games]) => ({
+ x: value,
+ y: games.length,
+ }));
+
+ return {
+ series: {
+ data: [
+ {
+ type: 'bar-x',
+ data,
+ name: 'Games released',
+ },
+ ],
+ },
+ xAxis: {
+ type: 'category',
+ categories: gamesByPlatform.map(([key]) => key),
+ title: {
+ text: 'Game Platforms',
+ },
+ labels: {
+ enabled: true,
+ rotation: 30,
+ },
+ },
+ yAxis: [{title: {text: 'Number of games released'}}],
+ };
+}
+
+const ChartStory = ({data}: {data: ChartKitWidgetData}) => {
+ const [shown, setShown] = React.useState(false);
+
+ if (!shown) {
+ settings.set({plugins: [D3Plugin]});
+ return ;
+ }
+
+ return (
+
+
+
+ );
+};
+
+export const PlaygroundBarXChartStory: StoryObj = {
+ name: 'Playground',
+ args: {
+ data: prepareData(),
+ },
+ argTypes: {
+ data: {
+ control: 'object',
+ },
+ },
+};
+
+export default {
+ title: 'Plugins/D3/Bar-X',
+ component: ChartStory,
+};
diff --git a/src/plugins/d3/examples/bar-x/Basic.tsx b/src/plugins/d3/examples/bar-x/Basic.tsx
index 789b0ae3..65c4d973 100644
--- a/src/plugins/d3/examples/bar-x/Basic.tsx
+++ b/src/plugins/d3/examples/bar-x/Basic.tsx
@@ -40,6 +40,7 @@ export const BasicBarXChart = () => {
text: 'Game Platforms',
},
},
+ yAxis: [{title: {text: 'Number of games released'}}],
};
return ;
diff --git a/src/plugins/d3/renderer/components/AxisX.tsx b/src/plugins/d3/renderer/components/AxisX.tsx
index 4c3f0e7c..c804e215 100644
--- a/src/plugins/d3/renderer/components/AxisX.tsx
+++ b/src/plugins/d3/renderer/components/AxisX.tsx
@@ -59,7 +59,7 @@ export const AxisX = React.memo(({axis, width, height, scale}: Props) => {
labelsStyle: axis.labels.style,
count: getTicksCount({axis, range: width}),
maxTickCount: getMaxTickCount({axis, width}),
- autoRotation: axis.labels.autoRotation,
+ rotation: axis.labels.rotation,
},
domain: {
size: width,
@@ -70,22 +70,19 @@ export const AxisX = React.memo(({axis, width, height, scale}: Props) => {
const svgElement = select(ref.current);
svgElement.selectAll('*').remove();
- svgElement
- .call(xAxisGenerator)
- .attr('class', b())
- .style('font-size', axis.labels.style.fontSize);
+ svgElement.call(xAxisGenerator).attr('class', b());
// add an axis header if necessary
if (axis.title.text) {
- const textY =
- axis.title.height + parseInt(axis.labels.style.fontSize) + axis.labels.padding;
+ const y =
+ axis.title.height + axis.title.margin + axis.labels.height + axis.labels.margin;
svgElement
.append('text')
.attr('class', b('title'))
.attr('text-anchor', 'middle')
.attr('x', width / 2)
- .attr('y', textY)
+ .attr('y', y)
.attr('font-size', axis.title.style.fontSize)
.text(axis.title.text)
.call(setEllipsisForOverflowText, width);
diff --git a/src/plugins/d3/renderer/components/AxisY.tsx b/src/plugins/d3/renderer/components/AxisY.tsx
index e3345fd9..4899d133 100644
--- a/src/plugins/d3/renderer/components/AxisY.tsx
+++ b/src/plugins/d3/renderer/components/AxisY.tsx
@@ -100,7 +100,7 @@ export const AxisY = ({axises, width, height, scale}: Props) => {
.remove();
if (axis.title.text) {
- const textY = axis.title.height + axis.labels.margin;
+ const textY = axis.title.margin + axis.labels.margin + axis.labels.width;
svgElement
.append('text')
diff --git a/src/plugins/d3/renderer/components/Chart.tsx b/src/plugins/d3/renderer/components/Chart.tsx
index f438cb97..9020b810 100644
--- a/src/plugins/d3/renderer/components/Chart.tsx
+++ b/src/plugins/d3/renderer/components/Chart.tsx
@@ -17,6 +17,9 @@ import {AxisX} from './AxisX';
import {Legend} from './Legend';
import {Title} from './Title';
import {Tooltip, TooltipTriggerArea} from './Tooltip';
+import {getPreparedXAxis} from '../hooks/useChartOptions/x-axis';
+import {getWidthOccupiedByYAxis} from '../hooks/useChartDimensions/utils';
+import {getPreparedYAxis} from '../hooks/useChartOptions/y-axis';
import './styles.scss';
@@ -37,9 +40,19 @@ export const Chart = (props: Props) => {
const dispatcher = React.useMemo(() => {
return getD3Dispatcher();
}, []);
- const {chart, title, tooltip, xAxis, yAxis} = useChartOptions({
+ const {chart, title, tooltip} = useChartOptions({
data,
});
+ const xAxis = React.useMemo(
+ () => getPreparedXAxis({xAxis: data.xAxis, width, series: data.series.data}),
+ [data, width],
+ );
+
+ const yAxis = React.useMemo(
+ () => getPreparedYAxis({series: data.series.data, yAxis: data.yAxis}),
+ [data, width],
+ );
+
const {
legendItems,
legendConfig,
@@ -87,6 +100,9 @@ export const Chart = (props: Props) => {
svgContainer: svgRef.current,
});
+ const boundsOffsetTop = chart.margin.top;
+ const boundsOffsetLeft = chart.margin.left + getWidthOccupiedByYAxis({preparedAxis: yAxis});
+
return (