All files / components/AxisLabel AxisLabel.tsx

0% Statements 0/19
0% Branches 0/16
0% Functions 0/1
0% Lines 0/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123                                                                                                                                                                                                                                                     
import _ from 'lodash';
import React from 'react';
import PropTypes from 'react-peek/prop-types';
import { lucidClassNames } from '../../util/style-helpers';
import { StandardProps, omitProps } from '../../util/component-types';
 
const cx = lucidClassNames.bind('&-AxisLabel');
 
const { number, string, oneOf, object } = PropTypes;
 
const defaultProps = {
	color: '#000',
};
 
export interface IAxisLabelProps extends StandardProps {
	/** Height of the margin this label should fit into. */
	height: number;
 
	/** Width of the margin this label should fit into. */
	width: number;
 
	/** Strings should match an existing color class unless they start with a '#' 
	 * for specific colors. E.g.:
	 * 
		- \`COLOR_0\`
		- \`COLOR_GOOD\`
		- \`'#123abc'\`
	`*/
	color: string;
 
	/** Contents of the label, should only ever be a string since we use a
		\`text\` under the hood. */
	label: string;
 
	/** Determine orientation of the label. */
	orient: 'top' | 'bottom' | 'left' | 'right';
}
 
export const AxisLabel = (props: IAxisLabelProps): React.ReactElement => {
	const {
		height,
		width,
		orient,
		label,
		color,
		style,
		className,
		...passThroughs
	} = props;
 
	const isH = orient === 'top' || orient === 'bottom';
	const isCustomColor = _.startsWith(color, '#');
	const colorStyle = isCustomColor ? { fill: color } : null;
 
	return (
		<text
			{...omitProps(passThroughs, undefined, _.keys(AxisLabel.propTypes))}
			style={{
				...colorStyle,
				...style,
			}}
			className={cx(className, '&', {
				[`&-${color}`]: !isCustomColor,
			})}
			x={isH ? width / 2 : (height / 2) * -1}
			y={orient === 'right' ? width : orient === 'bottom' ? height : 0}
			dy={orient === 'top' || orient === 'left' ? '1em' : '-.32em'}
			transform={isH ? '' : 'rotate(-90)'}
		>
			{label}
		</text>
	);
};
 
AxisLabel.defaultProps = defaultProps;
AxisLabel.displayName = 'AxisLabel';
AxisLabel.peek = {
	description: `
		\`AxisLabel\` is used within a \`svg\`
 
		Centered labels for axes that typically are fit into the margins of a
		chart.
	`,
	categories: ['visualizations', 'chart primitives'],
};
AxisLabel.propTypes = {
	style: object`
		Passed through to the root element.
	`,
 
	className: string`
		Appended to the component-specific class names set on the root element.
	`,
 
	height: number.isRequired`
		Height of the margin this label should fit into.
	`,
 
	width: number.isRequired`
		Width of the margin this label should fit into.
	`,
 
	color: string`
		Strings should match an existing color class unless they start with a '#'
		for specific colors. E.g.:
 
		- \`COLOR_0\`
		- \`COLOR_GOOD\`
		- \`'#123abc'\`
	`,
 
	label: string`
		Contents of the label, should only ever be a string since we use a
		\`text\` under the hood.
	`,
 
	orient: oneOf(['top', 'bottom', 'left', 'right'])`
		Determine orientation of the label.
	`,
};
 
export default AxisLabel;