lucid-ui
Version:
A UI component library from AppNexus.
235 lines • 20.5 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
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.PureToolTip = exports.Bars = void 0;
var lodash_1 = __importDefault(require("lodash"));
var react_1 = __importStar(require("react"));
var prop_types_1 = __importDefault(require("react-peek/prop-types"));
var style_helpers_1 = require("../../util/style-helpers");
var chart_helpers_1 = require("../../util/chart-helpers");
var component_types_1 = require("../../util/component-types");
var d3Scale = __importStar(require("d3-scale"));
var chartConstants = __importStar(require("../../constants/charts"));
//import shallowCompare from 'react-addons-shallow-compare';
var Bar_1 = __importDefault(require("../Bar/Bar"));
var ToolTip_1 = require("../ToolTip/ToolTip");
var Legend_1 = __importDefault(require("../Legend/Legend"));
// memoizing to maintain referential equality across renders, for performance
// optimization with shallow comparison
var memoizedExtractFields = lodash_1.default.memoize(chart_helpers_1.extractFields);
var memoizedStackByFields = lodash_1.default.memoize(chart_helpers_1.stackByFields);
var cx = style_helpers_1.lucidClassNames.bind('&-Bars');
var arrayOf = prop_types_1.default.arrayOf, func = prop_types_1.default.func, number = prop_types_1.default.number, object = prop_types_1.default.object, bool = prop_types_1.default.bool, string = prop_types_1.default.string;
var Bars = /** @class */ (function (_super) {
__extends(Bars, _super);
function Bars() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.defaultTooltipFormatter = function (dataPoint) {
var _a = _this.props, colorMap = _a.colorMap, colorOffset = _a.colorOffset, isStacked = _a.isStacked, legend = _a.legend, palette = _a.palette, yFields = _a.yFields, yFormatter = _a.yFormatter, yTooltipFormatter = _a.yTooltipFormatter;
return (react_1.default.createElement(Legend_1.default, { hasBorders: false, isReversed: isStacked }, lodash_1.default.map(yFields, function (field, fieldIndex) { return (react_1.default.createElement(Legend_1.default.Item, { key: fieldIndex, hasPoint: true, pointKind: 1, color: lodash_1.default.get(colorMap, field, palette[(fieldIndex + colorOffset) % palette.length]) }, yTooltipFormatter(lodash_1.default.get(legend, field, field), yFormatter(dataPoint[field], dataPoint), dataPoint[field]))); })));
};
_this.handleMouseEnter = function (hoveringSeriesIndex) {
_this.setState({
hoveringSeriesIndex: hoveringSeriesIndex,
});
};
_this.handleMouseOut = function () {
_this.setState({ hoveringSeriesIndex: null });
};
_this.state = {
hoveringSeriesIndex: null,
};
return _this;
}
Bars.prototype.render = function () {
var _this = this;
var _a = this.props, className = _a.className, data = _a.data, hasToolTips = _a.hasToolTips, palette = _a.palette, colorMap = _a.colorMap, colorOffset = _a.colorOffset, xScale = _a.xScale, xField = _a.xField, xFormatter = _a.xFormatter, yScaleOriginal = _a.yScale, yFields = _a.yFields, yStackedMax = _a.yStackedMax, renderTooltipBody = _a.renderTooltipBody, isStacked = _a.isStacked, passThroughs = __rest(_a, ["className", "data", "hasToolTips", "palette", "colorMap", "colorOffset", "xScale", "xField", "xFormatter", "yScale", "yFields", "yStackedMax", "renderTooltipBody", "isStacked"]);
var hoveringSeriesIndex = this.state.hoveringSeriesIndex;
// This scale is used for grouped bars
var innerXScale = d3Scale
.scaleBand()
.domain(lodash_1.default.times(yFields.length, function (num) { return "" + num; }))
.range([0, xScale.bandwidth()])
.round(true);
// Copy the original so we can mutate it
var yScale = yScaleOriginal.copy();
// If we are stacked, we need to calculate a new domain based on the sum of
// the various series' y data. One row per series.
var transformedData = isStacked
? memoizedStackByFields(data, yFields)
: memoizedExtractFields(data, yFields, yScale.domain()[0]);
// If we are stacked, we need to calculate a new domain based on the sum of
// the various group's y data
if (isStacked) {
yScale.domain([
yScale.domain()[0],
//@ts-ignore
yStackedMax || lodash_1.default.max(lodash_1.default.map(transformedData, function (x) { return lodash_1.default.last(lodash_1.default.last(x)); })),
]);
}
return (react_1.default.createElement("g", __assign({}, component_types_1.omitProps(passThroughs, undefined, lodash_1.default.keys(Bars.propTypes)), { className: cx(className, '&') }), lodash_1.default.map(transformedData, function (series, seriesIndex) { return (react_1.default.createElement("g", { key: seriesIndex },
lodash_1.default.map(series, function (_a, pointsIndex) {
var start = _a[0], end = _a[1];
return (react_1.default.createElement(Bar_1.default, { key: pointsIndex, x: isStacked
? // @ts-ignore
xScale(data[seriesIndex][xField])
: // prettier-ignore
// @ts-ignore
innerXScale(pointsIndex) +
// prettier-ignore
// @ts-ignore
xScale(data[seriesIndex][xField]), y: yScale(end), height: yScale(start) - yScale(end), width: isStacked ? xScale.bandwidth() : innerXScale.bandwidth(), color: lodash_1.default.get(colorMap, yFields[pointsIndex], palette[(pointsIndex + colorOffset) % palette.length]) }));
}),
react_1.default.createElement(PureToolTip, { isExpanded: hasToolTips && hoveringSeriesIndex === seriesIndex, height: isStacked
? // prettier-ignore
//@ts-ignore
yScale.range()[0] - yScale(lodash_1.default.last(series)[1])
: // prettier-ignore
//@ts-ignore
yScale.range()[0] - yScale(lodash_1.default.max(lodash_1.default.flatten(series))), width: xScale.bandwidth(),
// @ts-ignore
x: xScale(data[seriesIndex][xField]), y: yScale(lodash_1.default.max(lodash_1.default.flatten(series))), series: series, seriesIndex: seriesIndex, onMouseEnter: _this.handleMouseEnter, onMouseOut: _this.handleMouseOut, xFormatter: xFormatter, xField: xField, renderBody: renderTooltipBody || _this.defaultTooltipFormatter, data: data }))); })));
};
Bars.displayName = 'Bars';
Bars.peek = {
description: "\n\t\t\t\t*For use within an `svg`*\n\n\t\t\t\tBars are typically used to represent categorical data and can be\n\t\t\t\tstacked or grouped.\n\t\t\t",
categories: ['visualizations', 'chart primitives'],
madeFrom: ['Bar', 'ToolTip', 'Legend'],
};
Bars.propTypes = {
className: string(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n\t\t\tAppended to the component-specific class names set on the root element.\n\t\t"], ["\n\t\t\tAppended to the component-specific class names set on the root element.\n\t\t"]))),
data: arrayOf(object).isRequired(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n\t\t\tDe-normalized data\n\n\t\t\t\t[\n\t\t\t\t\t{ x: 'one', y0: 1, y1: 2, y2: 3, y3: 5 },\n\t\t\t\t\t{ x: 'two', y0: 2, y1: 3, y2: 4, y3: 6 },\n\t\t\t\t\t{ x: 'three', y0: 2, y1: 4, y2: 5, y3: 6 },\n\t\t\t\t\t{ x: 'four', y0: 3, y1: 6, y2: 7, y3: 7 },\n\t\t\t\t\t{ x: 'five', y0: 4, y1: 8, y2: 9, y3: 8 },\n\t\t\t\t]\n\t\t"], ["\n\t\t\tDe-normalized data\n\n\t\t\t\t[\n\t\t\t\t\t{ x: 'one', y0: 1, y1: 2, y2: 3, y3: 5 },\n\t\t\t\t\t{ x: 'two', y0: 2, y1: 3, y2: 4, y3: 6 },\n\t\t\t\t\t{ x: 'three', y0: 2, y1: 4, y2: 5, y3: 6 },\n\t\t\t\t\t{ x: 'four', y0: 3, y1: 6, y2: 7, y3: 7 },\n\t\t\t\t\t{ x: 'five', y0: 4, y1: 8, y2: 9, y3: 8 },\n\t\t\t\t]\n\t\t"]))),
legend: object(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n\t\t\tAn object with human readable names for fields that will be used for\n\t\t\ttooltips. E.g:\n\n\t\t\t\t{\n\t\t\t\t\trev: 'Revenue',\n\t\t\t\t\timps: 'Impressions',\n\t\t\t\t}\n\t\t"], ["\n\t\t\tAn object with human readable names for fields that will be used for\n\t\t\ttooltips. E.g:\n\n\t\t\t\t{\n\t\t\t\t\trev: 'Revenue',\n\t\t\t\t\timps: 'Impressions',\n\t\t\t\t}\n\t\t"]))),
hasToolTips: bool(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n\t\t Show tool tips on hover.\n\t\t"], ["\n\t\t Show tool tips on hover.\n\t\t"]))),
palette: arrayOf(string)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n\t\t\tTakes one of the palettes exported from `lucid.chartConstants`.\n\t\t\tAvailable palettes:\n\n\t\t\t- `PALETTE_7` (default)\n\t\t\t- `PALETTE_30`\n\t\t\t- `PALETTE_MONOCHROME_0_5`\n\t\t\t- `PALETTE_MONOCHROME_1_5`\n\t\t\t- `PALETTE_MONOCHROME_2_5`\n\t\t\t- `PALETTE_MONOCHROME_3_5`\n\t\t\t- `PALETTE_MONOCHROME_4_5`\n\t\t\t- `PALETTE_MONOCHROME_5_5`\n\t\t\t- `PALETTE_MONOCHROME_6_5`\n\t\t"], ["\n\t\t\tTakes one of the palettes exported from \\`lucid.chartConstants\\`.\n\t\t\tAvailable palettes:\n\n\t\t\t- \\`PALETTE_7\\` (default)\n\t\t\t- \\`PALETTE_30\\`\n\t\t\t- \\`PALETTE_MONOCHROME_0_5\\`\n\t\t\t- \\`PALETTE_MONOCHROME_1_5\\`\n\t\t\t- \\`PALETTE_MONOCHROME_2_5\\`\n\t\t\t- \\`PALETTE_MONOCHROME_3_5\\`\n\t\t\t- \\`PALETTE_MONOCHROME_4_5\\`\n\t\t\t- \\`PALETTE_MONOCHROME_5_5\\`\n\t\t\t- \\`PALETTE_MONOCHROME_6_5\\`\n\t\t"]))),
colorMap: object(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n\t\t\tYou can pass in an object if you want to map fields to\n\t\t\t`lucid.chartConstants` or custom colors:\n\n\t\t\t\t{\n\t\t\t\t\t'imps': COLOR_0,\n\t\t\t\t\t'rev': COLOR_3,\n\t\t\t\t\t'clicks': '#abc123',\n\t\t\t\t}\n\t\t"], ["\n\t\t\tYou can pass in an object if you want to map fields to\n\t\t\t\\`lucid.chartConstants\\` or custom colors:\n\n\t\t\t\t{\n\t\t\t\t\t'imps': COLOR_0,\n\t\t\t\t\t'rev': COLOR_3,\n\t\t\t\t\t'clicks': '#abc123',\n\t\t\t\t}\n\t\t"]))),
xScale: func.isRequired(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n\t\t\tThe scale for the x axis. Must be a d3 band scale. Lucid exposes the\n\t\t\t`lucid.d3Scale.scaleBand` library for use here.\n\t\t"], ["\n\t\t\tThe scale for the x axis. Must be a d3 band scale. Lucid exposes the\n\t\t\t\\`lucid.d3Scale.scaleBand\\` library for use here.\n\t\t"]))),
xField: string(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n\t\t\tThe field we should look up your x data by.\n\t\t"], ["\n\t\t\tThe field we should look up your x data by.\n\t\t"]))),
xFormatter: func(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n\t\t\tFunction to format the x data.\n\t\t"], ["\n\t\t\tFunction to format the x data.\n\t\t"]))),
yScale: func.isRequired(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n\t\t\tThe scale for the y axis. Must be a d3 scale. Lucid exposes the\n\t\t\t`lucid.d3Scale` library for use here.\n\t\t"], ["\n\t\t\tThe scale for the y axis. Must be a d3 scale. Lucid exposes the\n\t\t\t\\`lucid.d3Scale\\` library for use here.\n\t\t"]))),
yFields: arrayOf(string)(templateObject_11 || (templateObject_11 = __makeTemplateObject(["\n\t\t\tThe field(s) we should look up your y data by. Each entry represents a\n\t\t\tseries. Your actual y data should be numeric.\n\t\t"], ["\n\t\t\tThe field(s) we should look up your y data by. Each entry represents a\n\t\t\tseries. Your actual y data should be numeric.\n\t\t"]))),
yFormatter: func(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n\t\t\tFunction to format the y data.\n\t\t"], ["\n\t\t\tFunction to format the y data.\n\t\t"]))),
yStackedMax: number(templateObject_13 || (templateObject_13 = __makeTemplateObject(["\n\t\t\tTypically this number can be derived from the yScale. However when we're\n\t\t\t`isStacked` we need to calculate a new domain for the yScale based on\n\t\t\tthe sum of the data. If you need explicit control of the y max when\n\t\t\tstacking, pass it in here.\n\t\t"], ["\n\t\t\tTypically this number can be derived from the yScale. However when we're\n\t\t\t\\`isStacked\\` we need to calculate a new domain for the yScale based on\n\t\t\tthe sum of the data. If you need explicit control of the y max when\n\t\t\tstacking, pass it in here.\n\t\t"]))),
yTooltipFormatter: func(templateObject_14 || (templateObject_14 = __makeTemplateObject(["\n\t\t\tAn optional function used to format your y axis titles and data in the\n\t\t\ttooltips. The first value is the name of your y field, the second value\n\t\t\tis your post-formatted y value, and the third value is your non-formatted\n\t\t\ty-value. Signature: `(yField, yValueFormatted, yValue) => {}`\n\t\t"], ["\n\t\t\tAn optional function used to format your y axis titles and data in the\n\t\t\ttooltips. The first value is the name of your y field, the second value\n\t\t\tis your post-formatted y value, and the third value is your non-formatted\n\t\t\ty-value. Signature: \\`(yField, yValueFormatted, yValue) => {}\\`\n\t\t"]))),
isStacked: bool(templateObject_15 || (templateObject_15 = __makeTemplateObject(["\n\t\t\tThis will stack the data instead of grouping it. In order to stack the\n\t\t\tdata we have to calculate a new domain for the y scale that is based on\n\t\t\tthe `sum` of the data.\n\t\t"], ["\n\t\t\tThis will stack the data instead of grouping it. In order to stack the\n\t\t\tdata we have to calculate a new domain for the y scale that is based on\n\t\t\tthe \\`sum\\` of the data.\n\t\t"]))),
colorOffset: number(templateObject_16 || (templateObject_16 = __makeTemplateObject(["\n\t\t\tSometimes you might not want the colors to start rotating at the blue\n\t\t\tcolor, this number will be added the bar index in determining which color\n\t\t\tthe bars are.\n\t\t"], ["\n\t\t\tSometimes you might not want the colors to start rotating at the blue\n\t\t\tcolor, this number will be added the bar index in determining which color\n\t\t\tthe bars are.\n\t\t"]))),
renderTooltipBody: func(templateObject_17 || (templateObject_17 = __makeTemplateObject(["\n\t\t\tAn optional function used to format the entire tooltip body. The only arg is\n\t\t\tthe associated data point. This formatter will over-ride yTooltipFormatter\n\t\t\tand yAxisTooltipDataFormatter. Signature:\n\t\t\t`dataPoint => {}`\n\t\t"], ["\n\t\t\tAn optional function used to format the entire tooltip body. The only arg is\n\t\t\tthe associated data point. This formatter will over-ride yTooltipFormatter\n\t\t\tand yAxisTooltipDataFormatter. Signature:\n\t\t\t\\`dataPoint => {}\\`\n\t\t"]))),
};
Bars.defaultProps = {
hasToolTips: true,
xField: 'x',
xFormatter: lodash_1.default.identity,
yFields: ['y'],
yFormatter: lodash_1.default.identity,
yTooltipFormatter: function (yField, yValueFormatted) {
return yField + ": " + yValueFormatted;
},
renderTooltipBody: null,
isStacked: false,
colorOffset: 0,
palette: chartConstants.PALETTE_7,
};
return Bars;
}(react_1.PureComponent));
exports.Bars = Bars;
var PureToolTip = /** @class */ (function (_super) {
__extends(PureToolTip, _super);
function PureToolTip() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.handleMouseEnter = function () {
_this.props.onMouseEnter(_this.props.seriesIndex);
};
return _this;
}
PureToolTip.prototype.render = function () {
var _a = this.props, isExpanded = _a.isExpanded, height = _a.height, width = _a.width, x = _a.x, y = _a.y, seriesIndex = _a.seriesIndex, onMouseOut = _a.onMouseOut, renderBody = _a.renderBody, data = _a.data, xFormatter = _a.xFormatter, xField = _a.xField;
return (react_1.default.createElement(ToolTip_1.ToolTipDumb, { isExpanded: isExpanded, flyOutMaxWidth: 'none', isLight: true },
react_1.default.createElement(ToolTip_1.ToolTipDumb.Target, { elementType: 'g' },
react_1.default.createElement("rect", { className: cx('&-tooltip-hover-zone'), height: height, width: width, x: x, y: y, onMouseEnter: this.handleMouseEnter, onMouseOut: onMouseOut })),
react_1.default.createElement(ToolTip_1.ToolTipDumb.Title, null, xFormatter(
//@ts-ignore
data[seriesIndex][xField], data[seriesIndex])),
react_1.default.createElement(ToolTip_1.ToolTipDumb.Body, null, renderBody(data[seriesIndex]))));
};
PureToolTip.displayName = 'PureToolTip';
PureToolTip._isPrivate = true;
PureToolTip.propTypes = {
data: arrayOf(object),
height: number,
isExpanded: bool,
onMouseEnter: func,
onMouseOut: func,
renderBody: func,
seriesIndex: number,
width: number,
x: number,
xField: string,
xFormatter: func,
y: number,
};
return PureToolTip;
}(react_1.PureComponent));
exports.PureToolTip = PureToolTip;
exports.default = Bars;
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17;
//# sourceMappingURL=Bars.js.map