@nafr/echo-ui
Version:
A UI library born for WAA
54 lines (53 loc) • 2.37 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { scaleLinear, select, axisRight, axisBottom } from 'd3';
import { cn } from '../../../lib/utils';
import { useStyle } from './styles';
import { MAX, MIN, TICKS, TICK_SIZE } from './constants';
export const Axis = forwardRef((props, ref) => {
const { min = MIN, max = MAX, ticks = TICKS, tickSize = TICK_SIZE, vertical = false, relatedRef, ...restProps } = props;
useImperativeHandle(ref, () => svgRef.current);
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
const svgRef = useRef(null);
useEffect(() => {
initAxis();
}, [min, max, tickSize, vertical, ticks, width, height, relatedRef]);
const initAxis = () => {
if (svgRef.current === null)
return;
const element = svgRef.current;
if (relatedRef?.current) {
setWidth(relatedRef.current.clientWidth);
setHeight(relatedRef.current.clientHeight);
}
else {
const { height, width } = element.getBoundingClientRect();
setWidth(width);
setHeight(height);
}
// Clear previous axis
select(element).selectAll('*').remove();
// Set up scales and axes
const yScale = scaleLinear().domain([min, max]).range([height, 0]);
const yAxis = axisRight(yScale).ticks(ticks).tickSize(tickSize);
const xScale = scaleLinear().domain([min, max]).range([0, width]);
const xAxis = axisBottom(xScale).ticks(ticks).tickSize(tickSize);
const svg = select(svgRef.current);
let axisGroup;
if (vertical)
axisGroup = svg.append('g').classed('y-axis', true).call(yAxis);
else
axisGroup = svg.append('g').classed('x-axis', true).call(xAxis);
// Positioning axis
if (!vertical)
axisGroup.attr('transform', `translate(0,${height})`);
// Remove axis line
svg.select('.domain').style('display', 'none');
};
return (_jsx("svg", { ...restProps, ref: svgRef, className: cn(useStyle({ vertical }), restProps.className), style: {
...restProps.style,
width: vertical ? 20 : width,
height: vertical ? height : 20,
} }));
});