Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions semcore/base-components/src/components/flex-box/Box/useBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,16 @@ export type BoxProps = IStyledProps & {
children?: React.ReactNode;
/** Hover cursor */
hoverCursor?: Property.Cursor;
/**
* Background
*/
/** Css `background` property */
bg?: Property.Background | BasicColorKeys | SemanticColorKeys;
/**
* Border radius
*/
/** Css `border-radius` property */
borderRadius?: Property.BorderRadius | BorderRadius;
/**
* Border
*/
/** Css `border` property */
border?: Property.Border;

/** Css `resize` property */
resize?: Property.Resize;
/** Css `overflow` property */
overflow?: Property.Overflow;
/**
* Old way to add custom style
* @deprecated
Expand Down Expand Up @@ -254,6 +251,8 @@ function calculateIndentStyles(props: BoxProps, scaleIndent: number, colorResolv
getAutoOrScaleIndent(props['px'], scaleIndent),

border: props.border,
resize: props.resize,
overflow: props.overflow,
borderRadius: props.borderRadius ? colorResolver(props.borderRadius) : undefined,
backgroundColor: props.bg ? colorResolver(props.bg) : undefined,
});
Expand All @@ -277,7 +276,9 @@ export default function useBox<T extends BoxProps>(
bg,
border,
borderRadius,
resize,
flex,
overflow,
w,
h,
wMin,
Expand Down Expand Up @@ -351,6 +352,8 @@ export default function useBox<T extends BoxProps>(
border,
borderRadius,
bg,
resize,
overflow,
]);

const styles = sstyled(style);
Expand Down
80 changes: 75 additions & 5 deletions semcore/d3-chart/src/component/Chart/AbstractChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import type { Intergalactic } from '@semcore/core';
import { Component, Root, sstyled } from '@semcore/core';
import { extractAriaProps } from '@semcore/core/lib/utils/ariaProps';
import { callAllEventHandlers } from '@semcore/core/lib/utils/assignProps';
import canUseDOM from '@semcore/core/lib/utils/canUseDOM';
import cssToIntDefault from '@semcore/core/lib/utils/cssToIntDefault';
import trottle from '@semcore/core/lib/utils/rafTrottle';
import { Text } from '@semcore/typography';
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3-scale';
import React, { Fragment } from 'react';
Expand All @@ -24,6 +27,9 @@ export type ChartState = {
dataDefinitions: Array<LegendItem & { columns: React.ReactNode[] }>;
highlightedLine: number;
withTrend: boolean;

plotWidth: number;
plotHeight: number;
};

export const NOT_A_VALUE = 'n/a';
Expand All @@ -45,9 +51,20 @@ export abstract class AbstractChart<

protected dataHints = makeDataHintsContainer();

protected chartRef = React.createRef<HTMLElement>();
protected legendRef = React.createRef<HTMLDivElement>();

private observer: ResizeObserver | undefined;

constructor(props: Props) {
super(props);

this.handleResize = trottle(this.handleResize.bind(this));

if (canUseDOM()) {
this.observer = new ResizeObserver(this.handleResize);
}

this.setHighlightedLine = this.setHighlightedLine.bind(this);
this.handleChangeVisible = this.handleChangeVisible.bind(this);
this.handleMouseEnter = this.handleMouseEnter.bind(this);
Expand All @@ -60,15 +77,25 @@ export abstract class AbstractChart<
dataDefinitions: this.getDefaultDataDefinitions(),
highlightedLine: -1,
withTrend: false,
plotWidth: props.plotWidth,
plotHeight: props.plotHeight,
} as State;
}

public componentDidMount(): void {
this.observer?.observe(this.chartRef.current!);
}

public componentDidUpdate(prevProps: Props) {
if (prevProps.data !== this.props.data || prevProps.legendProps !== this.props.legendProps) {
this.setState({ dataDefinitions: this.getDefaultDataDefinitions() });
}
}

public componentWillUnmount(): void {
this.observer?.disconnect();
}

protected getDefaultDataDefinitions(): Array<LegendItem & { columns: React.ReactNode[] }> {
const { data, legendProps } = this.props;

Expand Down Expand Up @@ -398,7 +425,7 @@ export abstract class AbstractChart<
};

if (lProps.legendType === 'Table') {
return <ChartLegendTable {...(commonLegendProps as LegendTableProps)} />;
return <ChartLegendTable {...(commonLegendProps as LegendTableProps)} ref={this.legendRef} />;
}

if ('withTrend' in lProps) {
Expand All @@ -410,10 +437,10 @@ export abstract class AbstractChart<
onTrendIsVisibleChange: this.handleWithTrendChange,
};

return <ChartLegend {...(flexLegendProps as LegendFlexProps)} />;
return <ChartLegend {...(flexLegendProps as LegendFlexProps)} ref={this.legendRef} />;
}

return <ChartLegend {...(commonLegendProps as LegendFlexProps)} />;
return <ChartLegend {...(commonLegendProps as LegendFlexProps)} ref={this.legendRef} />;
}

protected renderAxis(): React.ReactNode {
Expand Down Expand Up @@ -531,13 +558,14 @@ export abstract class AbstractChart<

public render() {
const SChart = Root;
const { styles, plotWidth, plotHeight, data, patterns, a11yAltTextConfig, duration, eventEmitter, showTooltip } =
const { styles, data, patterns, a11yAltTextConfig, duration, eventEmitter, showTooltip } =
this.asProps;
const { plotWidth, plotHeight } = this.state;

const { extractedAriaProps } = extractAriaProps(this.asProps);

return sstyled(styles)(
<SChart render={Flex} gap={5} __excludeProps={['data', 'eventEmitter']} role='group'>
<SChart render={Flex} gap={5} __excludeProps={['data', 'eventEmitter']} role='group' ref={this.chartRef}>
{this.renderLegend()}
<Plot
data={data}
Expand All @@ -558,4 +586,46 @@ export abstract class AbstractChart<
</SChart>,
);
}

private handleResize(entities: ResizeObserverEntry[]) {
const { aspect, direction, onResize } = this.asProps;
const chartElement = this.chartRef.current;

if (!chartElement) return;

const legendElement = this.legendRef.current;
const computedStyles = window.getComputedStyle(chartElement);

let width: number = chartElement.clientWidth;
let height: number = chartElement.clientHeight;

if (legendElement) {
const gap: number = cssToIntDefault(computedStyles.gap, 0);
if (direction?.includes('column')) {
height = height - legendElement.clientHeight - gap;
} else {
width = width - legendElement.clientWidth - gap;
}
}

if (aspect) {
const minHeight = cssToIntDefault(computedStyles.getPropertyValue('min-height'));
const maxHeight = cssToIntDefault(computedStyles.getPropertyValue('max-height'));
height = width * aspect;

if (height < minHeight) {
height = minHeight;
}
if (height > maxHeight) {
height = maxHeight;
}
}

this.setState({
plotWidth: width,
plotHeight: height,
});

onResize?.([width, height], entities);
}
}
10 changes: 8 additions & 2 deletions semcore/d3-chart/src/component/Chart/AbstractChart.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,14 @@ export type BaseChartProps<T extends ListData | ObjectData> = FlexProps & {
data: T;
/**
* Width of plot
* @deprecated. width is 100% of the parent element.
*/
plotWidth: number;
plotWidth?: number;
/**
* Height of plot
* @deprecated. height is 100% of the parent element.
*/
plotHeight: number;
plotHeight?: number;

/** Enables charts patterns that enhances charts accessibility */
patterns?: PatternsConfig;
Expand Down Expand Up @@ -158,6 +160,10 @@ export type BaseChartProps<T extends ListData | ObjectData> = FlexProps & {
* Flag to show/hide legend
*/
showLegend?: boolean;
/** Relation between height and width dimensions block */
aspect?: number;
/** Callback which will be called after changing the block size */
onResize?: (size: [number, number], entries: ResizeObserverEntry[]) => void;
/**
* Props for Legend
*/
Expand Down
6 changes: 4 additions & 2 deletions semcore/d3-chart/src/component/Chart/AreaChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class AreaChartComponent extends AbstractChart<
} as const;

get xScale() {
const { xScale, marginY = 40, plotWidth, data, groupKey } = this.asProps;
const { xScale, marginY = 40, data, groupKey } = this.asProps;
const { plotWidth } = this.state;

if (xScale) {
return xScale;
Expand All @@ -48,7 +49,8 @@ class AreaChartComponent extends AbstractChart<
}

get yScale(): ScaleLinear<any, any> {
const { yScale, marginX = 24, plotHeight, stacked } = this.asProps;
const { yScale, marginX = 24, stacked } = this.asProps;
const { plotHeight } = this.state;

if (yScale) {
return yScale;
Expand Down
6 changes: 3 additions & 3 deletions semcore/d3-chart/src/component/Chart/BarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,11 @@ class BarChartComponent extends AbstractChart<
const {
marginY = 40,
marginX = 24,
plotWidth,
plotHeight,
invertAxis,
data,
groupKey,
} = this.asProps;
const { plotWidth, plotHeight } = this.state;

const testItem = data[0][groupKey];
const range = invertAxis
Expand All @@ -291,7 +290,8 @@ class BarChartComponent extends AbstractChart<
}

private get valueScale() {
const { marginY = 40, marginX = 24, plotWidth, plotHeight, invertAxis, type } = this.asProps;
const { marginY = 40, marginX = 24, invertAxis, type } = this.asProps;
const { plotWidth, plotHeight } = this.state;

const max = type === 'stack' ? super.maxStackedValue : Math.max(...super.flatValues);

Expand Down
6 changes: 4 additions & 2 deletions semcore/d3-chart/src/component/Chart/BubbleChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ class BubbleChartComponent extends AbstractChart<
}

get xScale() {
const { xScale, marginY = 30, plotWidth, data } = this.asProps;
const { xScale, marginY = 30, data } = this.asProps;
const { plotWidth } = this.state;

if (xScale) {
return xScale;
Expand All @@ -85,7 +86,8 @@ class BubbleChartComponent extends AbstractChart<
}

get yScale(): ScaleLinear<any, any> {
const { yScale, marginX = 30, plotHeight, data } = this.asProps;
const { yScale, marginX = 30, data } = this.asProps;
const { plotHeight } = this.state;

if (yScale) {
return yScale;
Expand Down
17 changes: 10 additions & 7 deletions semcore/d3-chart/src/component/Chart/CigaretteChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ class CigaretteChartComponent extends AbstractChart<
}

private computeCigaretteItems() {
const { plotWidth, plotHeight, data, invertAxis, minimalBarWidth } = this.asProps;
const { data, invertAxis, minimalBarWidth } = this.asProps;
const { plotWidth, plotHeight } = this.state;

const dataDefinitions = invertAxis
? this.activeDataDefinitions
Expand Down Expand Up @@ -214,20 +215,21 @@ class CigaretteChartComponent extends AbstractChart<
};

get xScale() {
const { plotWidth } = this.asProps;
const { plotWidth } = this.state;

return scaleLinear([0, plotWidth]);
}

get yScale() {
const { plotHeight } = this.asProps;
const { plotHeight } = this.state;

return scaleLinear([plotHeight, 0]);
}

renderChart() {
const { invertAxis, data, uid, duration, patterns, plotHeight, plotWidth, onClick } =
const { invertAxis, data, uid, duration, patterns, onClick } =
this.asProps;
const { plotWidth, plotHeight } = this.state;
const { dataDefinitions, highlightedLine } = this.state;

this.offset = 0;
Expand Down Expand Up @@ -415,13 +417,14 @@ class CigaretteChartComponent extends AbstractChart<

override render() {
const SChart = Root;
const { styles, plotWidth, plotHeight, data, patterns, invertAxis, a11yAltTextConfig } = this.asProps;
const { styles, data, patterns, invertAxis, a11yAltTextConfig } = this.asProps;
const { plotWidth, plotHeight } = this.state;

const header = this.renderHeader();

if (invertAxis) {
return sstyled(styles)(
<SChart render={Flex} gap={6} direction='column' __excludeProps={['onClick', 'data']}>
<SChart render={Flex} gap={6} direction='column' __excludeProps={['onClick', 'data']} ref={this.chartRef}>
<Flex direction='column'>
{header}
<Plot
Expand All @@ -446,7 +449,7 @@ class CigaretteChartComponent extends AbstractChart<
}

return sstyled(styles)(
<SChart render={Flex} gap={6} __excludeProps={['onClick', 'data']}>
<SChart render={Flex} gap={6} __excludeProps={['onClick', 'data']} ref={this.chartRef}>
<Plot
ref={this.plotRef}
data={data}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ class CompactHorizontalBarChartComponent extends AbstractChart<
}

private get categoryScale() {
const { marginY = 40, plotHeight, data, y } = this.asProps;
const { marginY = 40, data, y } = this.asProps;
const { plotHeight } = this.state;

return scaleBand()
.range([plotHeight - marginY, marginY])
Expand All @@ -114,7 +115,8 @@ class CompactHorizontalBarChartComponent extends AbstractChart<
}

private get valueScale() {
const { marginY = 0, plotWidth } = this.asProps;
const { marginY = 0 } = this.asProps;
const { plotWidth } = this.state;

const sum = [...super.flatValues.values()].reduce((acc, d) => acc + d, 0);

Expand Down
Loading
Loading