@razorpay/blade
Version:
The Design System that powers Razorpay
307 lines (295 loc) • 15 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
import React__default, { useState, useEffect, useCallback, useMemo, isValidElement, cloneElement } from 'react';
import '../../../node_modules/recharts/es6/index.js';
import { animate } from 'framer-motion';
import '../utils/index.js';
import '../CommonChartComponents/index.js';
import { componentId } from '../CommonChartComponents/tokens.js';
import { componentIds } from './componentIds.js';
import { useLineChartContext, LineChartContext } from './LineChartContext.js';
import getIn from '../../../utils/lodashButBetter/get.js';
import '../../../utils/makeAnalyticsAttribute/index.js';
import '../../../utils/metaAttribute/index.js';
import '../../BladeProvider/index.js';
import '../../Box/BaseBox/index.js';
import '../../../utils/isValidAllowedChildren/index.js';
import '../../../utils/assignWithoutSideEffects/index.js';
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import useTheme from '../../BladeProvider/useTheme.js';
import useChartsColorTheme from '../utils/useColorTheme.js';
import { Line as Line$1 } from '../../../node_modules/recharts/es6/cartesian/Line.js';
import { assignWithoutSideEffects } from '../../../utils/assignWithoutSideEffects/assignWithoutSideEffects.js';
import { getComponentId } from '../../../utils/isValidAllowedChildren/isValidAllowedChildren.js';
import { assignDataColorMapping } from '../utils/assignDataColorMapping/assignDataColorMapping.js';
import { CommonChartComponentsContext } from '../CommonChartComponents/CommonChartComponentsContext.js';
import { BaseBox } from '../../Box/BaseBox/BaseBox.web.js';
import { metaAttribute } from '../../../utils/metaAttribute/metaAttribute.web.js';
import { makeAnalyticsAttribute } from '../../../utils/makeAnalyticsAttribute/makeAnalyticsAttribute.js';
import { ResponsiveContainer } from '../../../node_modules/recharts/es6/component/ResponsiveContainer.js';
import { LineChart } from '../../../node_modules/recharts/es6/chart/LineChart.js';
var _excluded = ["color", "strokeStyle", "type", "dot", "activeDot", "showLegend", "_index", "_colorTheme", "_totalLines", "hide", "dataKey"],
_excluded2 = ["children", "colorTheme", "testID", "data"];
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var Line = function Line(_ref) {
var color = _ref.color,
_ref$strokeStyle = _ref.strokeStyle,
strokeStyle = _ref$strokeStyle === void 0 ? 'solid' : _ref$strokeStyle,
_ref$type = _ref.type,
type = _ref$type === void 0 ? 'monotone' : _ref$type,
_ref$dot = _ref.dot,
dot = _ref$dot === void 0 ? false : _ref$dot,
_ref$activeDot = _ref.activeDot,
activeDot = _ref$activeDot === void 0 ? true : _ref$activeDot,
_ref$showLegend = _ref.showLegend,
showLegend = _ref$showLegend === void 0 ? true : _ref$showLegend,
_index = _ref._index,
_colorTheme = _ref._colorTheme,
_totalLines = _ref._totalLines,
hide = _ref.hide,
dataKey = _ref.dataKey,
props = _objectWithoutProperties(_ref, _excluded);
var _useTheme = useTheme(),
theme = _useTheme.theme;
var _useLineChartContext = useLineChartContext(),
hoveredDataKey = _useLineChartContext.hoveredDataKey,
setHoveredDataKey = _useLineChartContext.setHoveredDataKey;
var themeColors = useChartsColorTheme({
colorTheme: _colorTheme,
chartName: 'line',
chartDataIndicators: _totalLines
});
var isOtherLineHovered = hoveredDataKey !== null && hoveredDataKey !== dataKey;
var colorToken = getIn(theme.colors, color !== null && color !== void 0 ? color : themeColors[_index !== null && _index !== void 0 ? _index : 0]);
var strokeDasharray = strokeStyle === 'dashed' ? '5 5' : strokeStyle === 'dotted' ? '2 2' : undefined;
var isLineDotted = strokeStyle === 'dashed';
var animationBegin = isLineDotted ? theme.motion.delay.gentle + theme.motion.duration.xgentle : theme.motion.delay.gentle;
var animationDuration = theme.motion.duration.xgentle;
// Animated opacity using framer-motion
var targetOpacity = isOtherLineHovered ? 0.2 : 1;
var _useState = useState(targetOpacity),
_useState2 = _slicedToArray(_useState, 2),
animatedOpacity = _useState2[0],
setAnimatedOpacity = _useState2[1];
useEffect(function () {
var controls = animate(animatedOpacity, targetOpacity, {
duration: 0.5,
ease: 'easeInOut',
onUpdate: function onUpdate(latest) {
return setAnimatedOpacity(latest);
}
});
return function () {
return controls.stop();
};
}, [targetOpacity]);
var updateHoveredDataKey = useCallback(function (key) {
if (!hide) {
setHoveredDataKey === null || setHoveredDataKey === void 0 || setHoveredDataKey(key);
}
}, [hide, setHoveredDataKey]);
var handleMouseEnter = useCallback(function () {
updateHoveredDataKey(dataKey);
}, [dataKey, updateHoveredDataKey]);
var handleMouseLeave = useCallback(function () {
updateHoveredDataKey(null);
}, [updateHoveredDataKey]);
// activeDot config with hover handlers
var activeDotConfig = useMemo(function () {
return activeDot ? {
onMouseEnter: function onMouseEnter() {
return updateHoveredDataKey(dataKey);
},
onMouseLeave: function onMouseLeave() {
return updateHoveredDataKey(null);
}
} : false;
}, [activeDot, dataKey, updateHoveredDataKey]);
return /*#__PURE__*/jsxs(Fragment, {
children: [/*#__PURE__*/jsx(Line$1, {
type: "monotone",
dataKey: dataKey,
stroke: "transparent",
strokeWidth: 15,
dot: false,
activeDot: false,
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave,
connectNulls: true,
legendType: "none",
tooltipType: "none",
hide: hide
}, "line-".concat(dataKey, "-background")), /*#__PURE__*/jsx(Line$1, _objectSpread({
stroke: colorToken,
strokeWidth: 1.5,
strokeDasharray: strokeDasharray,
type: type,
dataKey: dataKey,
activeDot: isOtherLineHovered ? false : activeDotConfig,
dot: dot,
legendType: showLegend ? 'line' : 'none',
animationBegin: animationBegin,
animationDuration: animationDuration,
strokeLinecap: "round",
strokeLinejoin: "round",
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave,
hide: hide
// Animated opacity using framer-motion
,
strokeOpacity: animatedOpacity,
isAnimationActive: true
}, props), "line-".concat(dataKey, "-main"))]
});
};
var ChartLine = /*#__PURE__*/assignWithoutSideEffects(Line, {
componentId: componentIds.ChartLine
});
// Main components
var ChartLineWrapper = function ChartLineWrapper(_ref2) {
var children = _ref2.children,
_ref2$colorTheme = _ref2.colorTheme,
colorTheme = _ref2$colorTheme === void 0 ? 'categorical' : _ref2$colorTheme,
testID = _ref2.testID,
data = _ref2.data,
restProps = _objectWithoutProperties(_ref2, _excluded2);
var themeColors = useChartsColorTheme({
colorTheme: colorTheme,
chartName: 'line'
});
// State to track which line is currently hovered
var _useState3 = useState(null),
_useState4 = _slicedToArray(_useState3, 2),
hoveredDataKey = _useState4[0],
setHoveredDataKey = _useState4[1];
var _useState5 = useState(undefined),
_useState6 = _slicedToArray(_useState5, 2),
selectedDataKeys = _useState6[0],
setSelectedDataKeys = _useState6[1];
/**
* We need to check child of CharLineWrapper. if they have any custom color we store that.
* We need these mapping because colors of tooltip & legend is determine based on this
* recharts do provide a color but it is hex code and we need blade color token .
*/
var _useMemo = useMemo(function () {
var childrenArray = React__default.Children.toArray(children);
var dataColorMapping = {};
// Count ChartLine components
var totalLines = childrenArray.filter(function (child) {
return /*#__PURE__*/isValidElement(child) && getComponentId(child) === componentIds.ChartLine;
}).length;
// Find ChartXAxis and extract secondaryDataKey
var secondaryDataKey;
var _iterator = _createForOfIteratorHelper(childrenArray),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var child = _step.value;
if (/*#__PURE__*/React__default.isValidElement(child) && getComponentId(child) === componentId.chartXAxis) {
var _child$props3;
secondaryDataKey = (_child$props3 = child.props) === null || _child$props3 === void 0 ? void 0 : _child$props3.secondaryDataKey;
break;
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
var LineChartIndex = 0;
var lineChartModifiedChildrens = React__default.Children.map(children, function (child) {
if (/*#__PURE__*/isValidElement(child) && getComponentId(child) === componentIds.ChartLine) {
var _child$props, _child$props2;
var childColor = child === null || child === void 0 || (_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.color;
var dataKey = child === null || child === void 0 || (_child$props2 = child.props) === null || _child$props2 === void 0 ? void 0 : _child$props2.dataKey;
if (dataKey) {
/**
* if we have custom color given by user we use that other wise we just
* assign theme colors to the dataColorMapping, in `assignDataColorMapping`
*/
dataColorMapping[dataKey] = {
colorToken: childColor,
isCustomColor: Boolean(childColor)
};
}
// Pass hide prop based on whether this line's dataKey is NOT in selectedDataKeys
// If selectedDataKeys is undefined, show all lines (default behavior)
return /*#__PURE__*/cloneElement(child, {
_index: LineChartIndex++,
_colorTheme: colorTheme,
_totalLines: totalLines,
hide: selectedDataKeys ? !selectedDataKeys.includes(dataKey) : false
});
}
return child;
});
assignDataColorMapping(dataColorMapping, themeColors);
return {
dataColorMapping: dataColorMapping,
lineChartModifiedChildrens: lineChartModifiedChildrens,
totalLines: totalLines,
secondaryDataKey: secondaryDataKey
};
}, [children, colorTheme, themeColors, selectedDataKeys]),
dataColorMapping = _useMemo.dataColorMapping,
lineChartModifiedChildrens = _useMemo.lineChartModifiedChildrens,
secondaryDataKey = _useMemo.secondaryDataKey;
// Build secondary label map internally from ChartXAxis's secondaryDataKey prop
var secondaryLabelMap = useMemo(function () {
if (!secondaryDataKey || !data) return undefined;
var map = {};
data.forEach(function (item, index) {
map[index] = item[secondaryDataKey];
});
return map;
}, [data, secondaryDataKey]);
// Memoize context values to prevent unnecessary re-renders of consumers
var lineChartContextValue = useMemo(function () {
return {
hoveredDataKey: hoveredDataKey,
setHoveredDataKey: setHoveredDataKey
};
}, [hoveredDataKey]);
var commonChartContextValue = useMemo(function () {
return {
chartName: 'line',
dataColorMapping: dataColorMapping,
selectedDataKeys: selectedDataKeys,
setSelectedDataKeys: setSelectedDataKeys,
secondaryLabelMap: secondaryLabelMap,
dataLength: data === null || data === void 0 ? void 0 : data.length
};
}, [dataColorMapping, selectedDataKeys, secondaryLabelMap, data === null || data === void 0 ? void 0 : data.length]);
return /*#__PURE__*/jsx(LineChartContext.Provider, {
value: lineChartContextValue,
children: /*#__PURE__*/jsx(CommonChartComponentsContext.Provider, {
value: commonChartContextValue,
children: /*#__PURE__*/jsx(BaseBox, _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, metaAttribute({
name: 'line-chart',
testID: testID
})), makeAnalyticsAttribute(restProps)), {}, {
width: "100%",
height: "100%"
}, restProps), {}, {
children: /*#__PURE__*/jsx(ResponsiveContainer, {
width: "100%",
height: "100%",
children: /*#__PURE__*/jsx(LineChart, {
data: data,
onMouseLeave: function onMouseLeave() {
return setHoveredDataKey(null);
},
children: lineChartModifiedChildrens
})
})
}))
})
});
};
export { ChartLine, ChartLineWrapper };
//# sourceMappingURL=LineChart.web.js.map