source: node_modules/recharts/lib/cartesian/Brush.js@ a762898

Last change on this file since a762898 was a762898, checked in by istevanoska <ilinastevanoska@…>, 5 months ago

Added visualizations

  • Property mode set to 100644
File size: 28.0 KB
Line 
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.Brush = Brush;
7exports.defaultBrushProps = void 0;
8var _react = _interopRequireWildcard(require("react"));
9var React = _react;
10var _clsx = require("clsx");
11var _d3Scale = require("victory-vendor/d3-scale");
12var _range = _interopRequireDefault(require("es-toolkit/compat/range"));
13var _Layer = require("../container/Layer");
14var _Text = require("../component/Text");
15var _ChartUtils = require("../util/ChartUtils");
16var _DataUtils = require("../util/DataUtils");
17var _CssPrefixUtils = require("../util/CssPrefixUtils");
18var _chartDataContext = require("../context/chartDataContext");
19var _brushUpdateContext = require("../context/brushUpdateContext");
20var _hooks = require("../state/hooks");
21var _chartDataSlice = require("../state/chartDataSlice");
22var _brushSlice = require("../state/brushSlice");
23var _PanoramaContext = require("../context/PanoramaContext");
24var _brushSelectors = require("../state/selectors/brushSelectors");
25var _useChartSynchronisation = require("../synchronisation/useChartSynchronisation");
26var _resolveDefaultProps = require("../util/resolveDefaultProps");
27var _svgPropertiesNoEvents = require("../util/svgPropertiesNoEvents");
28function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
29function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
30function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
31function 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; }
32function _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; }
33function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
34function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
35function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
36// Why is this tickFormatter different from the other TickFormatters? This one allows to return numbers too for some reason.
37
38function DefaultTraveller(props) {
39 var {
40 x,
41 y,
42 width,
43 height,
44 stroke
45 } = props;
46 var lineY = Math.floor(y + height / 2) - 1;
47 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
48 x: x,
49 y: y,
50 width: width,
51 height: height,
52 fill: stroke,
53 stroke: "none"
54 }), /*#__PURE__*/React.createElement("line", {
55 x1: x + 1,
56 y1: lineY,
57 x2: x + width - 1,
58 y2: lineY,
59 fill: "none",
60 stroke: "#fff"
61 }), /*#__PURE__*/React.createElement("line", {
62 x1: x + 1,
63 y1: lineY + 2,
64 x2: x + width - 1,
65 y2: lineY + 2,
66 fill: "none",
67 stroke: "#fff"
68 }));
69}
70function Traveller(props) {
71 var {
72 travellerProps,
73 travellerType
74 } = props;
75 if (/*#__PURE__*/React.isValidElement(travellerType)) {
76 // @ts-expect-error element cloning disagrees with the types (and it should)
77 return /*#__PURE__*/React.cloneElement(travellerType, travellerProps);
78 }
79 if (typeof travellerType === 'function') {
80 return travellerType(travellerProps);
81 }
82 return /*#__PURE__*/React.createElement(DefaultTraveller, travellerProps);
83}
84function getNameFromUnknown(value) {
85 if ((0, _DataUtils.isNotNil)(value) && typeof value === 'object' && 'name' in value && typeof value.name === 'string') {
86 return value.name;
87 }
88 return undefined;
89}
90function getAriaLabel(data, startIndex, endIndex) {
91 var start = getNameFromUnknown(data[startIndex]);
92 var end = getNameFromUnknown(data[endIndex]);
93 return "Min value: ".concat(start, ", Max value: ").concat(end);
94}
95function TravellerLayer(_ref) {
96 var {
97 otherProps,
98 travellerX,
99 id,
100 onMouseEnter,
101 onMouseLeave,
102 onMouseDown,
103 onTouchStart,
104 onTravellerMoveKeyboard,
105 onFocus,
106 onBlur
107 } = _ref;
108 var {
109 y,
110 x: xFromProps,
111 travellerWidth,
112 height,
113 traveller,
114 ariaLabel,
115 data,
116 startIndex,
117 endIndex
118 } = otherProps;
119 var x = Math.max(travellerX, xFromProps);
120 var travellerProps = _objectSpread(_objectSpread({}, (0, _svgPropertiesNoEvents.svgPropertiesNoEvents)(otherProps)), {}, {
121 x,
122 y,
123 width: travellerWidth,
124 height
125 });
126 var ariaLabelBrush = ariaLabel || getAriaLabel(data, startIndex, endIndex);
127 return /*#__PURE__*/React.createElement(_Layer.Layer, {
128 tabIndex: 0,
129 role: "slider",
130 "aria-label": ariaLabelBrush,
131 "aria-valuenow": travellerX,
132 className: "recharts-brush-traveller",
133 onMouseEnter: onMouseEnter,
134 onMouseLeave: onMouseLeave,
135 onMouseDown: onMouseDown,
136 onTouchStart: onTouchStart,
137 onKeyDown: e => {
138 if (!['ArrowLeft', 'ArrowRight'].includes(e.key)) {
139 return;
140 }
141 e.preventDefault();
142 e.stopPropagation();
143 onTravellerMoveKeyboard(e.key === 'ArrowRight' ? 1 : -1, id);
144 },
145 onFocus: onFocus,
146 onBlur: onBlur,
147 style: {
148 cursor: 'col-resize'
149 }
150 }, /*#__PURE__*/React.createElement(Traveller, {
151 travellerType: traveller,
152 travellerProps: travellerProps
153 }));
154}
155/*
156 * This one cannot be a React Component because React is not happy with it returning only string | number.
157 * React wants a full React.JSX.Element but that is not compatible with Text component.
158 */
159function getTextOfTick(props) {
160 var {
161 index,
162 data,
163 tickFormatter,
164 dataKey
165 } = props;
166 // @ts-expect-error getValueByDataKey does not validate the output type
167 var text = (0, _ChartUtils.getValueByDataKey)(data[index], dataKey, index);
168 return typeof tickFormatter === 'function' ? tickFormatter(text, index) : text;
169}
170function getIndexInRange(valueRange, x) {
171 var len = valueRange.length;
172 var start = 0;
173 var end = len - 1;
174 while (end - start > 1) {
175 var middle = Math.floor((start + end) / 2);
176 var middleValue = valueRange[middle];
177 if (middleValue != null && middleValue > x) {
178 end = middle;
179 } else {
180 start = middle;
181 }
182 }
183 var endValue = valueRange[end];
184 return endValue != null && x >= endValue ? end : start;
185}
186function getIndex(_ref2) {
187 var {
188 startX,
189 endX,
190 scaleValues,
191 gap,
192 data
193 } = _ref2;
194 var lastIndex = data.length - 1;
195 var min = Math.min(startX, endX);
196 var max = Math.max(startX, endX);
197 var minIndex = getIndexInRange(scaleValues, min);
198 var maxIndex = getIndexInRange(scaleValues, max);
199 return {
200 startIndex: minIndex - minIndex % gap,
201 endIndex: maxIndex === lastIndex ? lastIndex : maxIndex - maxIndex % gap
202 };
203}
204function Background(_ref3) {
205 var {
206 x,
207 y,
208 width,
209 height,
210 fill,
211 stroke
212 } = _ref3;
213 return /*#__PURE__*/React.createElement("rect", {
214 stroke: stroke,
215 fill: fill,
216 x: x,
217 y: y,
218 width: width,
219 height: height
220 });
221}
222function BrushText(_ref4) {
223 var {
224 startIndex,
225 endIndex,
226 y,
227 height,
228 travellerWidth,
229 stroke,
230 tickFormatter,
231 dataKey,
232 data,
233 startX,
234 endX
235 } = _ref4;
236 var offset = 5;
237 var attrs = {
238 pointerEvents: 'none',
239 fill: stroke
240 };
241 return /*#__PURE__*/React.createElement(_Layer.Layer, {
242 className: "recharts-brush-texts"
243 }, /*#__PURE__*/React.createElement(_Text.Text, _extends({
244 textAnchor: "end",
245 verticalAnchor: "middle",
246 x: Math.min(startX, endX) - offset,
247 y: y + height / 2
248 }, attrs), getTextOfTick({
249 index: startIndex,
250 tickFormatter,
251 dataKey,
252 data
253 })), /*#__PURE__*/React.createElement(_Text.Text, _extends({
254 textAnchor: "start",
255 verticalAnchor: "middle",
256 x: Math.max(startX, endX) + travellerWidth + offset,
257 y: y + height / 2
258 }, attrs), getTextOfTick({
259 index: endIndex,
260 tickFormatter,
261 dataKey,
262 data
263 })));
264}
265function Slide(_ref5) {
266 var {
267 y,
268 height,
269 stroke,
270 travellerWidth,
271 startX,
272 endX,
273 onMouseEnter,
274 onMouseLeave,
275 onMouseDown,
276 onTouchStart
277 } = _ref5;
278 var x = Math.min(startX, endX) + travellerWidth;
279 var width = Math.max(Math.abs(endX - startX) - travellerWidth, 0);
280 return /*#__PURE__*/React.createElement("rect", {
281 className: "recharts-brush-slide",
282 onMouseEnter: onMouseEnter,
283 onMouseLeave: onMouseLeave,
284 onMouseDown: onMouseDown,
285 onTouchStart: onTouchStart,
286 style: {
287 cursor: 'move'
288 },
289 stroke: "none",
290 fill: stroke,
291 fillOpacity: 0.2,
292 x: x,
293 y: y,
294 width: width,
295 height: height
296 });
297}
298function Panorama(_ref6) {
299 var {
300 x,
301 y,
302 width,
303 height,
304 data,
305 children,
306 padding
307 } = _ref6;
308 var isPanoramic = React.Children.count(children) === 1;
309 if (!isPanoramic) {
310 return null;
311 }
312 var chartElement = _react.Children.only(children);
313 if (!chartElement) {
314 return null;
315 }
316 return /*#__PURE__*/React.cloneElement(chartElement, {
317 x,
318 y,
319 width,
320 height,
321 margin: padding,
322 compact: true,
323 data
324 });
325}
326var createScale = _ref7 => {
327 var {
328 data,
329 startIndex,
330 endIndex,
331 x,
332 width,
333 travellerWidth
334 } = _ref7;
335 if (!data || !data.length) {
336 return {};
337 }
338 var len = data.length;
339 var scale = (0, _d3Scale.scalePoint)().domain((0, _range.default)(0, len)).range([x, x + width - travellerWidth]);
340 var scaleValues = scale.domain().map(entry => scale(entry)).filter(_DataUtils.isNotNil);
341 return {
342 isTextActive: false,
343 isSlideMoving: false,
344 isTravellerMoving: false,
345 isTravellerFocused: false,
346 startX: scale(startIndex),
347 endX: scale(endIndex),
348 scale,
349 scaleValues
350 };
351};
352var isTouch = e => e.changedTouches && !!e.changedTouches.length;
353class BrushWithState extends _react.PureComponent {
354 constructor(props) {
355 super(props);
356 _defineProperty(this, "handleDrag", e => {
357 if (this.leaveTimer) {
358 clearTimeout(this.leaveTimer);
359 this.leaveTimer = null;
360 }
361 if (this.state.isTravellerMoving) {
362 this.handleTravellerMove(e);
363 } else if (this.state.isSlideMoving) {
364 this.handleSlideDrag(e);
365 }
366 });
367 _defineProperty(this, "handleTouchMove", e => {
368 var _e$changedTouches;
369 var touch = (_e$changedTouches = e.changedTouches) === null || _e$changedTouches === void 0 ? void 0 : _e$changedTouches[0];
370 if (touch != null) {
371 this.handleDrag(touch);
372 }
373 });
374 _defineProperty(this, "handleDragEnd", () => {
375 this.setState({
376 isTravellerMoving: false,
377 isSlideMoving: false
378 }, () => {
379 var {
380 endIndex,
381 onDragEnd,
382 startIndex
383 } = this.props;
384 onDragEnd === null || onDragEnd === void 0 || onDragEnd({
385 endIndex,
386 startIndex
387 });
388 });
389 this.detachDragEndListener();
390 });
391 _defineProperty(this, "handleLeaveWrapper", () => {
392 if (this.state.isTravellerMoving || this.state.isSlideMoving) {
393 this.leaveTimer = window.setTimeout(this.handleDragEnd, this.props.leaveTimeOut);
394 }
395 });
396 _defineProperty(this, "handleEnterSlideOrTraveller", () => {
397 this.setState({
398 isTextActive: true
399 });
400 });
401 _defineProperty(this, "handleLeaveSlideOrTraveller", () => {
402 this.setState({
403 isTextActive: false
404 });
405 });
406 _defineProperty(this, "handleSlideDragStart", e => {
407 var event = isTouch(e) ? e.changedTouches[0] : e;
408 if (event == null) {
409 return;
410 }
411 this.setState({
412 isTravellerMoving: false,
413 isSlideMoving: true,
414 slideMoveStartX: event.pageX
415 });
416 this.attachDragEndListener();
417 });
418 _defineProperty(this, "handleTravellerMoveKeyboard", (direction, id) => {
419 var {
420 data,
421 gap,
422 startIndex,
423 endIndex
424 } = this.props;
425 // scaleValues are a list of coordinates. For example: [65, 250, 435, 620, 805, 990].
426 var {
427 scaleValues,
428 startX,
429 endX
430 } = this.state;
431 if (scaleValues == null) {
432 return;
433 }
434
435 // unless we search for the closest scaleValue to the current coordinate
436 // we need to move travelers via index when using the keyboard
437 var currentIndex = -1;
438 if (id === 'startX') {
439 currentIndex = startIndex;
440 } else if (id === 'endX') {
441 currentIndex = endIndex;
442 }
443 if (currentIndex < 0 || currentIndex >= data.length) {
444 return;
445 }
446 var newIndex = currentIndex + direction;
447 if (newIndex === -1 || newIndex >= scaleValues.length) {
448 return;
449 }
450 var newScaleValue = scaleValues[newIndex];
451 if (newScaleValue == null) {
452 return;
453 }
454
455 // Prevent travellers from being on top of each other or overlapping
456 if (id === 'startX' && newScaleValue >= endX || id === 'endX' && newScaleValue <= startX) {
457 return;
458 }
459 this.setState(
460 // @ts-expect-error not sure why typescript is not happy with this, partial update is fine in React
461 {
462 [id]: newScaleValue
463 }, () => {
464 this.props.onChange(getIndex({
465 startX: this.state.startX,
466 endX: this.state.endX,
467 data,
468 gap,
469 scaleValues
470 }));
471 });
472 });
473 this.travellerDragStartHandlers = {
474 startX: this.handleTravellerDragStart.bind(this, 'startX'),
475 endX: this.handleTravellerDragStart.bind(this, 'endX')
476 };
477 this.state = {
478 brushMoveStartX: 0,
479 movingTravellerId: undefined,
480 endX: 0,
481 startX: 0,
482 slideMoveStartX: 0
483 };
484 }
485 static getDerivedStateFromProps(nextProps, prevState) {
486 var {
487 data,
488 width,
489 x,
490 travellerWidth,
491 startIndex,
492 endIndex,
493 startIndexControlledFromProps,
494 endIndexControlledFromProps
495 } = nextProps;
496 if (data !== prevState.prevData) {
497 return _objectSpread({
498 prevData: data,
499 prevTravellerWidth: travellerWidth,
500 prevX: x,
501 prevWidth: width
502 }, data && data.length ? createScale({
503 data,
504 width,
505 x,
506 travellerWidth,
507 startIndex,
508 endIndex
509 }) : {
510 scale: undefined,
511 scaleValues: undefined
512 });
513 }
514 var prevScale = prevState.scale;
515 if (prevScale && (width !== prevState.prevWidth || x !== prevState.prevX || travellerWidth !== prevState.prevTravellerWidth)) {
516 prevScale.range([x, x + width - travellerWidth]);
517 var scaleValues = prevScale.domain().map(entry => prevScale(entry)).filter(value => value != null);
518 return {
519 prevData: data,
520 prevTravellerWidth: travellerWidth,
521 prevX: x,
522 prevWidth: width,
523 startX: prevScale(nextProps.startIndex),
524 endX: prevScale(nextProps.endIndex),
525 scaleValues
526 };
527 }
528 if (prevState.scale && !prevState.isSlideMoving && !prevState.isTravellerMoving && !prevState.isTravellerFocused && !prevState.isTextActive) {
529 /*
530 * If the startIndex or endIndex are controlled from the outside,
531 * we need to keep the startX and end up to date.
532 * Also we do not want to do that while user is interacting in the brush,
533 * because this will trigger re-render and interrupt the drag&drop.
534 */
535 if (startIndexControlledFromProps != null && prevState.prevStartIndexControlledFromProps !== startIndexControlledFromProps) {
536 return {
537 startX: prevState.scale(startIndexControlledFromProps),
538 prevStartIndexControlledFromProps: startIndexControlledFromProps
539 };
540 }
541 if (endIndexControlledFromProps != null && prevState.prevEndIndexControlledFromProps !== endIndexControlledFromProps) {
542 return {
543 endX: prevState.scale(endIndexControlledFromProps),
544 prevEndIndexControlledFromProps: endIndexControlledFromProps
545 };
546 }
547 }
548 return null;
549 }
550 componentWillUnmount() {
551 if (this.leaveTimer) {
552 clearTimeout(this.leaveTimer);
553 this.leaveTimer = null;
554 }
555 this.detachDragEndListener();
556 }
557 attachDragEndListener() {
558 window.addEventListener('mouseup', this.handleDragEnd, true);
559 window.addEventListener('touchend', this.handleDragEnd, true);
560 window.addEventListener('mousemove', this.handleDrag, true);
561 }
562 detachDragEndListener() {
563 window.removeEventListener('mouseup', this.handleDragEnd, true);
564 window.removeEventListener('touchend', this.handleDragEnd, true);
565 window.removeEventListener('mousemove', this.handleDrag, true);
566 }
567 handleSlideDrag(e) {
568 var {
569 slideMoveStartX,
570 startX,
571 endX,
572 scaleValues
573 } = this.state;
574 if (scaleValues == null) {
575 return;
576 }
577 var {
578 x,
579 width,
580 travellerWidth,
581 startIndex,
582 endIndex,
583 onChange,
584 data,
585 gap
586 } = this.props;
587 var delta = e.pageX - slideMoveStartX;
588 if (delta > 0) {
589 delta = Math.min(delta, x + width - travellerWidth - endX, x + width - travellerWidth - startX);
590 } else if (delta < 0) {
591 delta = Math.max(delta, x - startX, x - endX);
592 }
593 var newIndex = getIndex({
594 startX: startX + delta,
595 endX: endX + delta,
596 data,
597 gap,
598 scaleValues
599 });
600 if ((newIndex.startIndex !== startIndex || newIndex.endIndex !== endIndex) && onChange) {
601 onChange(newIndex);
602 }
603 this.setState({
604 startX: startX + delta,
605 endX: endX + delta,
606 slideMoveStartX: e.pageX
607 });
608 }
609 handleTravellerDragStart(id, e) {
610 var event = isTouch(e) ? e.changedTouches[0] : e;
611 if (event == null) {
612 return;
613 }
614 this.setState({
615 isSlideMoving: false,
616 isTravellerMoving: true,
617 movingTravellerId: id,
618 brushMoveStartX: event.pageX
619 });
620 this.attachDragEndListener();
621 }
622 handleTravellerMove(e) {
623 var {
624 brushMoveStartX,
625 movingTravellerId,
626 endX,
627 startX,
628 scaleValues
629 } = this.state;
630 if (movingTravellerId == null || scaleValues == null) {
631 return;
632 }
633 var prevValue = this.state[movingTravellerId];
634 var {
635 x,
636 width,
637 travellerWidth,
638 onChange,
639 gap,
640 data
641 } = this.props;
642 var params = {
643 startX: this.state.startX,
644 endX: this.state.endX,
645 data,
646 gap,
647 scaleValues
648 };
649 var delta = e.pageX - brushMoveStartX;
650 if (delta > 0) {
651 delta = Math.min(delta, x + width - travellerWidth - prevValue);
652 } else if (delta < 0) {
653 delta = Math.max(delta, x - prevValue);
654 }
655 params[movingTravellerId] = prevValue + delta;
656 var newIndex = getIndex(params);
657 var {
658 startIndex,
659 endIndex
660 } = newIndex;
661 var isFullGap = () => {
662 var lastIndex = data.length - 1;
663 if (movingTravellerId === 'startX' && (endX > startX ? startIndex % gap === 0 : endIndex % gap === 0) || endX < startX && endIndex === lastIndex || movingTravellerId === 'endX' && (endX > startX ? endIndex % gap === 0 : startIndex % gap === 0) || endX > startX && endIndex === lastIndex) {
664 return true;
665 }
666 return false;
667 };
668 this.setState(
669 // @ts-expect-error not sure why typescript is not happy with this, partial update is fine in React
670 {
671 [movingTravellerId]: prevValue + delta,
672 brushMoveStartX: e.pageX
673 }, () => {
674 if (onChange) {
675 if (isFullGap()) {
676 onChange(newIndex);
677 }
678 }
679 });
680 }
681 render() {
682 var {
683 data,
684 className,
685 children,
686 x,
687 y,
688 dy,
689 width,
690 height,
691 alwaysShowText,
692 fill,
693 stroke,
694 startIndex,
695 endIndex,
696 travellerWidth,
697 tickFormatter,
698 dataKey,
699 padding
700 } = this.props;
701 var {
702 startX,
703 endX,
704 isTextActive,
705 isSlideMoving,
706 isTravellerMoving,
707 isTravellerFocused
708 } = this.state;
709 if (!data || !data.length || !(0, _DataUtils.isNumber)(x) || !(0, _DataUtils.isNumber)(y) || !(0, _DataUtils.isNumber)(width) || !(0, _DataUtils.isNumber)(height) || width <= 0 || height <= 0) {
710 return null;
711 }
712 var layerClass = (0, _clsx.clsx)('recharts-brush', className);
713 var style = (0, _CssPrefixUtils.generatePrefixStyle)('userSelect', 'none');
714 var calculatedY = y + (dy !== null && dy !== void 0 ? dy : 0);
715 return /*#__PURE__*/React.createElement(_Layer.Layer, {
716 className: layerClass,
717 onMouseLeave: this.handleLeaveWrapper,
718 onTouchMove: this.handleTouchMove,
719 style: style
720 }, /*#__PURE__*/React.createElement(Background, {
721 x: x,
722 y: calculatedY,
723 width: width,
724 height: height,
725 fill: fill,
726 stroke: stroke
727 }), /*#__PURE__*/React.createElement(_PanoramaContext.PanoramaContextProvider, null, /*#__PURE__*/React.createElement(Panorama, {
728 x: x,
729 y: calculatedY,
730 width: width,
731 height: height,
732 data: data,
733 padding: padding
734 }, children)), /*#__PURE__*/React.createElement(Slide, {
735 y: calculatedY,
736 height: height,
737 stroke: stroke,
738 travellerWidth: travellerWidth,
739 startX: startX,
740 endX: endX,
741 onMouseEnter: this.handleEnterSlideOrTraveller,
742 onMouseLeave: this.handleLeaveSlideOrTraveller,
743 onMouseDown: this.handleSlideDragStart,
744 onTouchStart: this.handleSlideDragStart
745 }), /*#__PURE__*/React.createElement(TravellerLayer, {
746 travellerX: startX,
747 id: "startX",
748 otherProps: _objectSpread(_objectSpread({}, this.props), {}, {
749 y: calculatedY
750 }),
751 onMouseEnter: this.handleEnterSlideOrTraveller,
752 onMouseLeave: this.handleLeaveSlideOrTraveller,
753 onMouseDown: this.travellerDragStartHandlers.startX,
754 onTouchStart: this.travellerDragStartHandlers.startX,
755 onTravellerMoveKeyboard: this.handleTravellerMoveKeyboard,
756 onFocus: () => {
757 this.setState({
758 isTravellerFocused: true
759 });
760 },
761 onBlur: () => {
762 this.setState({
763 isTravellerFocused: false
764 });
765 }
766 }), /*#__PURE__*/React.createElement(TravellerLayer, {
767 travellerX: endX,
768 id: "endX",
769 otherProps: _objectSpread(_objectSpread({}, this.props), {}, {
770 y: calculatedY
771 }),
772 onMouseEnter: this.handleEnterSlideOrTraveller,
773 onMouseLeave: this.handleLeaveSlideOrTraveller,
774 onMouseDown: this.travellerDragStartHandlers.endX,
775 onTouchStart: this.travellerDragStartHandlers.endX,
776 onTravellerMoveKeyboard: this.handleTravellerMoveKeyboard,
777 onFocus: () => {
778 this.setState({
779 isTravellerFocused: true
780 });
781 },
782 onBlur: () => {
783 this.setState({
784 isTravellerFocused: false
785 });
786 }
787 }), (isTextActive || isSlideMoving || isTravellerMoving || isTravellerFocused || alwaysShowText) && /*#__PURE__*/React.createElement(BrushText, {
788 startIndex: startIndex,
789 endIndex: endIndex,
790 y: calculatedY,
791 height: height,
792 travellerWidth: travellerWidth,
793 stroke: stroke,
794 tickFormatter: tickFormatter,
795 dataKey: dataKey,
796 data: data,
797 startX: startX,
798 endX: endX
799 }));
800 }
801}
802function BrushInternal(props) {
803 var dispatch = (0, _hooks.useAppDispatch)();
804 var chartData = (0, _chartDataContext.useChartData)();
805 var dataIndexes = (0, _chartDataContext.useDataIndex)();
806 var onChangeFromContext = (0, _react.useContext)(_brushUpdateContext.BrushUpdateDispatchContext);
807 var onChangeFromProps = props.onChange;
808 var {
809 startIndex: startIndexFromProps,
810 endIndex: endIndexFromProps
811 } = props;
812 (0, _react.useEffect)(() => {
813 // start and end index can be controlled from props, and we need them to stay up-to-date in the Redux state too
814 dispatch((0, _chartDataSlice.setDataStartEndIndexes)({
815 startIndex: startIndexFromProps,
816 endIndex: endIndexFromProps
817 }));
818 }, [dispatch, endIndexFromProps, startIndexFromProps]);
819 (0, _useChartSynchronisation.useBrushChartSynchronisation)();
820 var onChange = (0, _react.useCallback)(nextState => {
821 if (dataIndexes == null) {
822 return;
823 }
824 var {
825 startIndex,
826 endIndex
827 } = dataIndexes;
828 if (nextState.startIndex !== startIndex || nextState.endIndex !== endIndex) {
829 onChangeFromContext === null || onChangeFromContext === void 0 || onChangeFromContext(nextState);
830 onChangeFromProps === null || onChangeFromProps === void 0 || onChangeFromProps(nextState);
831 dispatch((0, _chartDataSlice.setDataStartEndIndexes)(nextState));
832 }
833 }, [onChangeFromProps, onChangeFromContext, dispatch, dataIndexes]);
834 var brushDimensions = (0, _hooks.useAppSelector)(_brushSelectors.selectBrushDimensions);
835 if (brushDimensions == null || dataIndexes == null || chartData == null || !chartData.length) {
836 return null;
837 }
838 var {
839 startIndex,
840 endIndex
841 } = dataIndexes;
842 var {
843 x,
844 y,
845 width
846 } = brushDimensions;
847 var contextProperties = {
848 data: chartData,
849 x,
850 y,
851 width,
852 startIndex,
853 endIndex,
854 onChange
855 };
856 return /*#__PURE__*/React.createElement(BrushWithState, _extends({}, props, contextProperties, {
857 startIndexControlledFromProps: startIndexFromProps !== null && startIndexFromProps !== void 0 ? startIndexFromProps : undefined,
858 endIndexControlledFromProps: endIndexFromProps !== null && endIndexFromProps !== void 0 ? endIndexFromProps : undefined
859 }));
860}
861function BrushSettingsDispatcher(props) {
862 var dispatch = (0, _hooks.useAppDispatch)();
863 (0, _react.useEffect)(() => {
864 dispatch((0, _brushSlice.setBrushSettings)(props));
865 return () => {
866 dispatch((0, _brushSlice.setBrushSettings)(null));
867 };
868 }, [dispatch, props]);
869 return null;
870}
871var defaultBrushProps = exports.defaultBrushProps = {
872 height: 40,
873 travellerWidth: 5,
874 gap: 1,
875 fill: '#fff',
876 stroke: '#666',
877 padding: {
878 top: 1,
879 right: 1,
880 bottom: 1,
881 left: 1
882 },
883 leaveTimeOut: 1000,
884 alwaysShowText: false
885};
886
887/**
888 * Renders a scrollbar that allows the user to zoom and pan in the chart along its XAxis.
889 * It also allows you to render a small overview of the chart inside the brush that is always visible
890 * and shows the full data set so that the user can see where they are zoomed in.
891 *
892 * If a chart is synchronized with other charts using the `syncId` prop on the chart,
893 * the brush will also synchronize the zooming and panning between all synchronized charts.
894 *
895 * @see {@link https://recharts.github.io/en-US/examples/BrushBarChart/ BarChart with Brush}
896 * @see {@link https://recharts.github.io/en-US/examples/SynchronizedLineChart/ Synchronized Brush}
897 *
898 * @consumes CartesianChartContext
899 */
900function Brush(outsideProps) {
901 var props = (0, _resolveDefaultProps.resolveDefaultProps)(outsideProps, defaultBrushProps);
902 return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(BrushSettingsDispatcher, {
903 height: props.height,
904 x: props.x,
905 y: props.y,
906 width: props.width,
907 padding: props.padding
908 }), /*#__PURE__*/React.createElement(BrushInternal, props));
909}
910Brush.displayName = 'Brush';
Note: See TracBrowser for help on using the repository browser.