UNPKG

lucid-ui

Version:

A UI component library from Xandr.

451 lines 20.4 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var d3Axis = __importStar(require("d3-axis")); var d3Shape = __importStar(require("d3-shape")); var d3Drag = __importStar(require("d3-drag")); var d3Selection = __importStar(require("d3-selection")); var d3Transition = __importStar(require("d3-transition")); var react_dom_1 = __importDefault(require("react-dom")); var d3Scale = __importStar(require("d3-scale")); var lodash_1 = __importDefault(require("lodash")); var d3Array = __importStar(require("d3-array")); var style_helpers_1 = require("../../util/style-helpers"); var d3_helpers_1 = require("./d3-helpers"); var cx = style_helpers_1.lucidClassNames.bind('&-DraggableLineChart'); var getAttributes = function (selection, obj) { return lodash_1.default.reduce(obj, function (acc, value) { // @ts-ignore acc[value] = selection.attr(value); return acc; }, {}); }; var DraggableLineChartD3 = /** @class */ (function () { function DraggableLineChartD3(selection, params) { var _this = this; this.setMouseDown = function (isMouseDown, mouseDownStep) { _this.params.isMouseDown = isMouseDown; _this.params.mouseDownStep = mouseDownStep; }; this.getIsMouseDown = function () { return _this.params.isMouseDown; }; this.getMouseDownStep = function () { return _this.params.mouseDownStep || 0; }; this.getHasRenderedPoint = function () { return !!_this.params.hasRenderedPoint; }; this.getHasRenderedLine = function () { return !!_this.params.hasRenderedLine; }; this.setHasRenderedPoint = function () { _this.params.hasRenderedPoint = true; }; this.setHasRenderedLine = function () { _this.params.hasRenderedLine = true; }; this.shouldShowPreselect = function () { var hasUserValues = lodash_1.default.some(_this.params.data, function (_a) { var y = _a.y; return y > 0; }); return !!_this.params.onPreselect && !hasUserValues; }; this.drag = function () { var _a = _this, xScale = _a.xScale, yScale = _a.yScale, renderLine = _a.renderLine, renderPoints = _a.renderPoints, selection = _a.selection; var _b = _this.params, cx = _b.cx, onDragEnd = _b.onDragEnd; var initialPosition; return d3Drag .drag() .on('start', function () { var activeDot = d3Selection.select(this); initialPosition = Number(activeDot.attr('cy')); }) .on('drag', function (pointData) { var _a = yScale.range(), max = _a[0], min = _a[1]; var activeDot = d3Selection.select(this); // @ts-ignore var adjMouseY = initialPosition + d3Selection.event.y; var newPointY = adjMouseY < min ? min : adjMouseY > max ? max : adjMouseY; var lines = selection.selectAll("path.".concat(cx('&-Line'))); pointData.y = Number(yScale.invert(newPointY)); activeDot.attr('cy', newPointY); var line = d3Shape .line() .x(function (chartData) { return xScale(chartData.x) || 0; }) .y(function (chartData) { return yScale(chartData.y); }); lines.attr('d', line); }) .on('end', function (d) { if (onDragEnd) onDragEnd(d.y, d.x); renderLine(); renderPoints(); }); }; this.renderXAxis = function () { var _a = _this.params, margin = _a.margin, height = _a.height, xAxisTicksVertical = _a.xAxisTicksVertical, dataIsCentered = _a.dataIsCentered, cx = _a.cx, xAxisRenderProp = _a.xAxisRenderProp, data = _a.data; var xGroup = (0, d3_helpers_1.getGroup)(_this.selection, "".concat(cx('&-Axis'))); xGroup .call(function (xAxis) { xAxis .attr('transform', "translate(".concat(0, ",").concat(margin.top, ")")) .call(d3_helpers_1.lucidXAxis, { xScale: _this.xScale, tickSize: margin.top + margin.bottom - height, xAxisRenderProp: xAxisRenderProp, dataIsCentered: dataIsCentered, data: data, }); if (xAxisTicksVertical) { xAxis.classed('Vert', true); } else { xAxis.classed('NoVert', true); } if (dataIsCentered) { xAxis.classed('Center', true); } }) .call(function () { return xGroup; }); }; this.renderYAxis = function () { var yGroup = (0, d3_helpers_1.getGroup)(_this.selection, 'yAxisGroup'); yGroup .call(function (yAxis) { var _a = _this.params, margin = _a.margin, cx = _a.cx, yAxisFormatter = _a.yAxisFormatter; yAxis .attr('transform', "translate(".concat(margin.left, ",").concat(0, ")")) .classed("".concat(cx('&-Axis')), true) .transition() .duration(500) .call(d3Axis .axisLeft(_this.yScale) .tickFormat(yAxisFormatter)); }) .call(function () { return yGroup; }); }; this.renderLine = function () { if (_this.shouldShowPreselect()) { return; } var _a = _this.params, dataIsCentered = _a.dataIsCentered, cx = _a.cx; if (!_this.getHasRenderedLine()) { if (dataIsCentered) { var innerXTickWidth = _this.xScale.step(); _this.selection .append('g') .append('path') .attr('class', "".concat(cx('&-Line'))) .attr('transform', "translate(".concat(innerXTickWidth / 2, ", 0)")); } else { _this.selection .append('g') .append('path') .attr('class', "".concat(cx('&-Line'))); } _this.setHasRenderedLine(); } var lines = _this.selection.selectAll("path.".concat(cx('&-Line'))); lines.datum(_this.params.data).enter(); lines .transition(d3Transition.transition().duration(100)) .attr('fill', 'none') .attr('d', d3Shape .line() .x(function (d) { return _this.xScale(d.x) || 0; }) .y(function (d) { return _this.yScale(d.y); })); }; this.renderEmptyRenderProp = function (height, width) { var emptyRenderProp = _this.params.emptyRenderProp; if (!emptyRenderProp || !_this.shouldShowPreselect()) { return; } var emptyDataObject = _this.selection.selectAll('.emptyRender'); if (emptyDataObject.empty()) { var emptyRender = _this.selection .selectAll('.overlayContainer') .append('foreignObject') .attr('height', height) .attr('width', width) .attr('x', _this.params.margin.left) .classed('emptyRender', true); emptyRender.html(function (value, num, node) { react_dom_1.default.render(emptyRenderProp(), node[0]); }); } }; this.renderPoints = function () { if (_this.shouldShowPreselect()) { return; } var _a = _this.params, data = _a.data, dataIsCentered = _a.dataIsCentered; var circle = _this.getHasRenderedPoint() ? _this.selection.selectAll('circle').data(data).join('circle') : _this.selection .append('g') .selectAll('circle') .data(data) .join('circle'); if (dataIsCentered) { var innerXTickWidth = _this.xScale.step(); circle // @ts-ignore .transition() .duration(100) .attr('cx', function (d) { return _this.xScale(d.x) || 0; }) .attr('cy', function (d) { return _this.yScale(d.y); }) .attr('r', 5) .attr('transform', "translate(".concat(innerXTickWidth / 2, ", 0)")) .style('fill', '#587EBA') .style('stroke', 'white') .style('stroke-width', 1); } else { circle // @ts-ignore .transition() .duration(100) .attr('cx', function (d) { return _this.xScale(d.x) || 0; }) .attr('cy', function (d) { return _this.yScale(d.y); }) .attr('r', 5) .style('fill', '#587EBA') .style('stroke', 'white') .style('stroke-width', 1); } if (!_this.getHasRenderedPoint()) circle.call(_this.drag()); _this.setHasRenderedPoint(); }; this.reRenderDragBox = function (_a) { var dragBox = _a.dragBox, mouseX = _a.mouseX, xLeft = _a.xLeft, xRight = _a.xRight, stepWidth = _a.stepWidth, stepCount = _a.stepCount; var isLeft = xLeft >= mouseX; var isRight = xRight <= mouseX; var mouseDownStep = _this.getMouseDownStep(); if (isLeft) { var difference = lodash_1.default.max([xLeft - mouseX, 0]) || 0; var rawStepsSelected = Math.floor(difference / stepWidth) + 2; var maxStepsAvailable = mouseDownStep + 1; var stepsSelected = lodash_1.default.min([rawStepsSelected, maxStepsAvailable]) || 1; var activeBoxWidth = stepsSelected * stepWidth; var nextXLeft = xRight - activeBoxWidth; dragBox.attr('x', nextXLeft); dragBox.attr('width', activeBoxWidth); } else if (isRight) { var difference = lodash_1.default.max([mouseX - xRight, 0]) || 0; var rawStepsSelected = Math.floor(difference / stepWidth) + 2; var maxStepsAvailable = stepCount - mouseDownStep; var stepsSelected = lodash_1.default.min([rawStepsSelected, maxStepsAvailable]) || 1; var activeBoxWidth = stepsSelected * stepWidth; dragBox.attr('x', xLeft); dragBox.attr('width', activeBoxWidth); } else { dragBox.attr('x', xLeft); dragBox.attr('width', stepWidth); } }; this.renderHoverTracker = function () { var _a = _this.params, height = _a.height, _b = _a.margin, top = _b.top, bottom = _b.bottom, data = _a.data, onPreselect = _a.onPreselect; var _c = _this, shouldShowPreselect = _c.shouldShowPreselect, setMouseDown = _c.setMouseDown, getIsMouseDown = _c.getIsMouseDown, getMouseDownStep = _c.getMouseDownStep, reRenderDragBox = _c.reRenderDragBox, xScale = _c.xScale, selection = _c.selection; if (!shouldShowPreselect()) { selection.selectAll('.overlayContainer').remove(); return; } var innerHeight = height - top - bottom; var stepWidth = xScale.step(); var stepCount = data.length; var overlayContainer = selection .append('g') .classed('overlayContainer', true) .attr('transform', "translate(".concat(0, ",").concat(top, ")")); _this.renderEmptyRenderProp(innerHeight, stepCount * stepWidth); var overlayTrack = overlayContainer.selectAll('rect').data(data).enter(); overlayTrack .append('rect') .attr('x', function (chartData) { return _this.xScale(chartData.x) || 0; }) .attr('y', 0) .attr('width', function (chartData) { return _this.xScale.step(); }) .attr('height', innerHeight) .classed(cx('&-overlayTrack'), true) // @ts-ignore .on('mouseenter', function (d, i, nodes) { if (!getIsMouseDown()) { d3Selection.select(nodes[i]).classed('active', true); } }) // @ts-ignore .on('mouseout', function (d, i, nodes) { if (!getIsMouseDown()) { d3Selection.select(nodes[i]).classed('active', false); } }) .on('mousedown', function (d, i) { d3Selection.selectAll('.active').classed('active', false); var currentTarget = d3Selection.select(this); var _a = getAttributes(currentTarget, [ 'x', 'y', 'width', 'height', ]), x = _a.x, y = _a.y, width = _a.width, height = _a.height; // @ts-ignore setMouseDown(true, i); var xLeft = +x; var xRight = +x + +width; // @ts-ignore var container = d3Selection.select(this.parentNode); container .append('rect') .attr('x', x) .attr('y', y) .attr('width', width) .attr('height', height) .classed(cx('&-overlayTrack'), true) .classed('active', true) .classed('dragBox', true) .on('mouseout', function () { // @ts-ignore var mouseX = d3Selection.mouse(this)[0]; var dragBox = selection.selectAll('.dragBox'); reRenderDragBox({ dragBox: dragBox, mouseX: mouseX, xLeft: xLeft, xRight: xRight, stepWidth: stepWidth, stepCount: stepCount, }); }) .on('mousemove', function () { // @ts-ignore var mouseX = d3Selection.mouse(this)[0]; var dragBox = selection.selectAll('.dragBox'); reRenderDragBox({ dragBox: dragBox, mouseX: mouseX, xLeft: xLeft, xRight: xRight, stepWidth: stepWidth, stepCount: stepCount, }); }) .on('mouseup', function () { var clickStep = getMouseDownStep(); var activeBox = selection.selectAll('.dragBox'); var _a = getAttributes(activeBox, ['x', 'width']), x = _a.x, width = _a.width; var isRight = xLeft === +x; var steps = Math.round(+width / stepWidth); var startingIndex = isRight ? clickStep : clickStep - steps + 1; var endingIndex = startingIndex + steps - 1; var updatedData = data.map(function (step, i) { return (__assign(__assign({}, step), { isSelected: i >= startingIndex && i <= endingIndex })); }); !!onPreselect && onPreselect(updatedData); setMouseDown(false); selection.selectAll('.dragBox').remove(); selection.selectAll('.overlayContainer').remove(); }); }); }; this.renderLineChart = function () { _this.renderXAxis(); _this.renderYAxis(); _this.renderHoverTracker(); _this.renderLine(); _this.renderPoints(); }; this.updateLineChart = function (data) { _this.params.data = data; _this.yScale.domain([ lodash_1.default.isUndefined(_this.params.yAxisMin) ? d3Array.min(_this.params.data, function (d) { return d.y; }) : _this.params.yAxisMin, d3Array.max(_this.params.data, function (d) { return d.y; }) || 10, ]); _this.renderLineChart(); }; this.selection = selection; this.params = params; if (params.dataIsCentered) { this.xScale = d3Scale .scalePoint() .domain(__spreadArray(__spreadArray([], this.params.data.map(function (d) { return d.x; }), true), [''], false)) .range([ this.params.margin.left, this.params.width - this.params.margin.right - this.params.margin.left, ]); } else { this.xScale = d3Scale .scalePoint() .domain(this.params.data.map(function (d) { return d.x; })) .range([ this.params.margin.left, this.params.width - this.params.margin.right - this.params.margin.left, ]); } this.yScale = d3Scale .scaleLinear() .domain([ lodash_1.default.isUndefined(this.params.yAxisMin) ? d3Array.min(this.params.data, function (d) { return d.y; }) : this.params.yAxisMin, d3Array.max(this.params.data, function (d) { return d.y; }) || 10, ]) .nice() .range([ this.params.height - this.params.margin.bottom, this.params.margin.top, ]); } return DraggableLineChartD3; }()); exports.default = DraggableLineChartD3; //# sourceMappingURL=DraggableLineChartD3.js.map