UNPKG

@mcdevsl/superset-ui

Version:
153 lines (140 loc) 4.36 kB
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* eslint-disable react/sort-prop-types, react/jsx-sort-default-props */ import React from 'react'; import PropTypes from 'prop-types'; import { ParentSize } from '@vx/responsive'; const propTypes = { className: PropTypes.string, width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), renderChart: PropTypes.func.isRequired, renderLegend: PropTypes.func.isRequired, position: PropTypes.oneOf(['top', 'left', 'bottom', 'right']), legendJustifyContent: PropTypes.oneOf(['center', 'flex-start', 'flex-end']), }; const defaultProps = { className: '', width: 'auto', height: 'auto', position: 'top', legendJustifyContent: undefined, }; const LEGEND_STYLE_BASE = { display: 'flex', flexGrow: 0, flexShrink: 0, order: -1, paddingTop: '5px', fontSize: '0.9em', }; const CHART_STYLE_BASE = { flexGrow: 1, flexShrink: 1, flexBasis: 'auto', position: 'relative', }; class WithLegend extends React.Component { getContainerDirection() { const { position } = this.props; switch (position) { case 'left': return 'row'; case 'right': return 'row-reverse'; case 'bottom': return 'column-reverse'; default: case 'top': return 'column'; } } getLegendJustifyContent() { const { legendJustifyContent, position } = this.props; if (legendJustifyContent) { return legendJustifyContent; } switch (position) { case 'left': return 'flex-start'; case 'right': return 'flex-start'; case 'bottom': return 'flex-end'; default: case 'top': return 'flex-end'; } } render() { const { className, width, height, position, renderChart, renderLegend } = this.props; const isHorizontal = position === 'left' || position === 'right'; const style = { display: 'flex', flexDirection: this.getContainerDirection(), }; if (width) { style.width = width; } if (height) { style.height = height; } const chartStyle = { ...CHART_STYLE_BASE }; if (isHorizontal) { chartStyle.width = 0; } else { chartStyle.height = 0; } const legendDirection = isHorizontal ? 'column' : 'row'; const legendStyle = { ...LEGEND_STYLE_BASE, flexDirection: legendDirection, justifyContent: this.getLegendJustifyContent(), }; const legendContainerStyle = { flexWrap: 'wrap', display: 'flex', flexDirection: legendDirection, }; return ( <div className={`with-legend ${className}`} style={style}> <div className="legend-container" style={legendStyle}> {renderLegend({ // Pass flexDirection for @vx/legend to arrange legend items direction: legendDirection, style: legendContainerStyle, })} </div> <div className="main-container" style={chartStyle}> <ParentSize> {parent => parent.width > 0 && parent.height > 0 ? // Only render when necessary renderChart(parent) : null } </ParentSize> </div> </div> ); } } WithLegend.propTypes = propTypes; WithLegend.defaultProps = defaultProps; export default WithLegend;