UNPKG

lucid-ui

Version:

A UI component library from Xandr.

309 lines (306 loc) 13.3 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PieChartDumb = void 0; var lodash_1 = __importStar(require("lodash")); var react_1 = __importDefault(require("react")); var prop_types_1 = __importDefault(require("prop-types")); var style_helpers_1 = require("../../util/style-helpers"); var d3Shape = __importStar(require("d3-shape")); var chartConstants = __importStar(require("../../constants/charts")); var state_management_1 = require("../../util/state-management"); var Line_1 = __importDefault(require("../../components/Line/Line")); var ToolTip_1 = require("../../components/ToolTip/ToolTip"); var PieChart_reducers_1 = __importDefault(require("./PieChart.reducers")); var cx = style_helpers_1.lucidClassNames.bind('&-PieChart'); var string = prop_types_1.default.string, number = prop_types_1.default.number, arrayOf = prop_types_1.default.arrayOf, bool = prop_types_1.default.bool, shape = prop_types_1.default.shape, object = prop_types_1.default.object, func = prop_types_1.default.func; var DONUT_WIDTH = 15; var HOVER_SCALE = 1.1; // duplicated in .less file var INNER_RADIUS = 0.5; var nonPassThroughs = [ 'style', 'className', 'height', 'width', 'margin', 'data', 'hasToolTips', 'hasStroke', 'palette', 'colorMap', 'ToolTip', 'isDonut', 'isHovering', 'hoveringIndex', 'onMouseOver', 'onMouseOut', 'donutWidth', 'xAxisField', 'xAxisFormatter', 'yAxisField', 'yAxisFormatter', 'initialState', 'callbackId', ]; var defaultProps = { height: 200, width: 200, // duplicated because `statics` aren't available during getDefaultProps margin: { top: 10, right: 10, bottom: 10, left: 10, }, palette: chartConstants.PALETTE_7, hasToolTips: true, hasStroke: true, isDonut: false, donutWidth: DONUT_WIDTH, ToolTip: ToolTip_1.ToolTipDumb.defaultProps, isHovering: false, hoveringIndex: 0, onMouseOver: lodash_1.default.noop, onMouseOut: lodash_1.default.noop, xAxisField: 'x', xAxisFormatter: lodash_1.default.identity, yAxisField: 'y', yAxisFormatter: lodash_1.default.identity, }; var PieChart = function (props) { var style = props.style, className = props.className, height = props.height, width = props.width, marginOriginal = props.margin, data = props.data, hasToolTips = props.hasToolTips, hasStroke = props.hasStroke, palette = props.palette, colorMap = props.colorMap, isDonut = props.isDonut, donutWidth = props.donutWidth, toolTipProps = props.ToolTip, isHovering = props.isHovering, hoveringIndex = props.hoveringIndex, xAxisField = props.xAxisField, xAxisFormatter = props.xAxisFormatter, yAxisField = props.yAxisField, yAxisFormatter = props.yAxisFormatter, passThroughs = __rest(props, ["style", "className", "height", "width", "margin", "data", "hasToolTips", "hasStroke", "palette", "colorMap", "isDonut", "donutWidth", "ToolTip", "isHovering", "hoveringIndex", "xAxisField", "xAxisFormatter", "yAxisField", "yAxisFormatter"]); var margin = __assign(__assign({}, PieChart.MARGIN), marginOriginal); var svgClasses = cx(className, '&'); var pieChartProps = (0, lodash_1.omit)((0, lodash_1.omit)(passThroughs, ToolTip_1.nonPassThroughs.concat(['callbackId'])), nonPassThroughs); // TODO: Consider displaying something specific when there is no data, // perhaps a loading indicator. if (lodash_1.default.isEmpty(data) || width < 1 || height < 1) { return (react_1.default.createElement("svg", __assign({}, pieChartProps, { style: style, className: svgClasses, width: width, height: height }))); } var innerWidth = width - margin.left - margin.right; var innerHeight = height - margin.top - margin.bottom; var outerRadius = Math.min(innerWidth, innerHeight) / 2; var pie = d3Shape.pie().sort(null); // needed to put the slices in proper order var pieData = pie(lodash_1.default.map(data, yAxisField)); var arc = d3Shape .arc() .innerRadius(isDonut ? outerRadius - donutWidth : INNER_RADIUS) .outerRadius(outerRadius); // Useful for capturing hovers when we're in donut mode var arcFull = d3Shape.arc().innerRadius(0).outerRadius(outerRadius); var handleMouseOut = function (_a) { var event = _a.event; props.onMouseOut({ props: props, event: event, }); }; var handleMouseOver = function (index, event) { props.onMouseOver(index, { props: props, event: event, }); }; return (react_1.default.createElement("svg", __assign({}, pieChartProps, { style: style, className: svgClasses, width: width, height: height }), react_1.default.createElement(ToolTip_1.ToolTipDumb, __assign({}, toolTipProps, { isLight: true, isExpanded: hasToolTips && isHovering, onMouseOver: lodash_1.default.noop, onMouseOut: handleMouseOut }), react_1.default.createElement(ToolTip_1.ToolTipDumb.Target, { elementType: 'g' }, react_1.default.createElement("g", { transform: "translate(".concat(margin.left, ", ").concat(margin.top, ")") }, react_1.default.createElement("g", { transform: "translate(".concat(innerWidth / 2, ", ").concat(innerHeight / 2, ")") }, lodash_1.default.map(pieData, function (pieDatum, index) { /* Even though innerRadius and outerRadius are set when constructing arc and arcFull, these functions still expect a type that includes innerRadius and outerRadius */ //@ts-ignore var arcFullData = arcFull(pieDatum); //@ts-ignore var arcData = arc(pieDatum); return (react_1.default.createElement("g", { key: index, className: cx('&-slice-group', { '&-slice-group-is-hovering': isHovering && hoveringIndex === index, }) }, react_1.default.createElement(Line_1.default, { key: index, className: cx('&-slice', { '&-slice-has-stroke': hasStroke, }), d: arcData, color: lodash_1.default.get(colorMap, (data && data[index][xAxisField]) || '', palette[index % palette.length]), transform: "scale(".concat(isHovering && hoveringIndex === index ? HOVER_SCALE : 1, ")") }), react_1.default.createElement("path", { className: cx('&-slice-hover'), d: arcFullData, transform: "scale(".concat(HOVER_SCALE, ")"), onMouseOver: lodash_1.default.partial(handleMouseOver, index), onMouseOut: hasToolTips ? lodash_1.default.noop : handleMouseOut }))); })))), react_1.default.createElement(ToolTip_1.ToolTipDumb.Title, null, xAxisFormatter(lodash_1.default.get(data, "[".concat(hoveringIndex, "].").concat(xAxisField)))), react_1.default.createElement(ToolTip_1.ToolTipDumb.Body, null, yAxisFormatter(lodash_1.default.get(data, "[".concat(hoveringIndex, "].").concat(yAxisField))))))); }; exports.PieChartDumb = PieChart; PieChart.displayName = 'PieChart'; PieChart.propTypes = { /** Styles that are passed through to the root container. */ style: object, /** Appended to the component-specific class names set on the root element. */ className: string, /** Height of the chart. */ height: number, /** Width of the chart. */ width: number, /** An object defining the margins of the chart. These margins typically contain the axis and labels. */ margin: shape({ top: number, right: number, bottom: number, left: number, }), /** Data for the chart. E.g. [ { x: 'Monday' , y: 1 } , { x: 'Tuesday' , y: 2 } , { x: 'Wednesday' , y: 3 } , { x: 'Thursday' , y: 2 } , { x: 'Friday' , y: 5 } , ] */ data: arrayOf(object), /** Show tool tips on hover. */ hasToolTips: bool, /** Determines if the pie slices have a stroke around them. */ hasStroke: bool, /** Takes one of the palettes exported from \`lucid.chartConstants\`. Available palettes: - \`PALETTE_7\` (default) - \`PALETTE_30\` - \`PALETTE_MONOCHROME_0_5\` - \`PALETTE_MONOCHROME_1_5\` - \`PALETTE_MONOCHROME_2_5\` - \`PALETTE_MONOCHROME_3_5\` - \`PALETTE_MONOCHROME_4_5\` - \`PALETTE_MONOCHROME_5_5\` - \`PALETTE_MONOCHROME_6_5\` */ palette: arrayOf(string), /** You can pass in an object if you want to map x values to \`lucid.chartConstants\` or custom colors: { 'imps': COLOR_0, 'rev': COLOR_3, 'clicks': '#abc123', } */ colorMap: object, /** An object of ToolTip props that are passed through to the underlying ToolTip component. */ ToolTip: shape(ToolTip_1.ToolTipDumb.propTypes), /** Show the pie chart as a donut with a hollow center. */ isDonut: bool, /** Controls the visibility of the tooltip and the size of the currently hovered slice. */ isHovering: bool, /** Determines which slice to scale up and which data to display in he tooltip. */ hoveringIndex: number, /** Called when the user hovers over a slice. Signature: */ onMouseOver: func, /** Called when the user hovers away from either the pie or the tooltip. */ onMouseOut: func, /** Width of the donut in px. */ donutWidth: number, /** The field we should look up your x data by. The data should be strings. */ xAxisField: string, /** An optional function used to format your x axis data. */ xAxisFormatter: func, /** The field we should look up your y data by. The data should be numeric. */ yAxisField: string, /** An optional function used to format your y axis data. */ yAxisFormatter: func, }; PieChart.peek = { description: "`PieChart` is used for categorical data when you want to show the relative size of each category to the whole. We use similar \"x\" and \"y\" terms to keep parity with the other charts even though a pie chart is really just key value based.", categories: ['visualizations', 'charts'], madeFrom: ['ToolTip'], }; PieChart.MARGIN = { top: 10, right: 10, bottom: 10, left: 10, }; PieChart.DONUT_WIDTH = DONUT_WIDTH; PieChart.HOVER_SCALE = HOVER_SCALE; PieChart.reducers = PieChart_reducers_1.default; PieChart.defaultProps = defaultProps; exports.default = (0, state_management_1.buildModernHybridComponent)(PieChart, { reducers: PieChart_reducers_1.default }); //# sourceMappingURL=PieChart.js.map