@spider-analyzer/timeline 5.0.8 → 5.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spider-analyzer/timeline",
3
- "version": "5.0.8",
3
+ "version": "5.0.9",
4
4
  "description": "React graphical component to display metric over time with a time selection feature.",
5
5
  "author": "Thibaut Raballand <spider.analyzer@gmail.com> (https://spider-analyzer.io)",
6
6
  "license": "MIT",
package/src/TimeLine.tsx CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  useRef,
8
8
  useState,
9
9
  } from 'react';
10
+ import { flushSync } from 'react-dom';
10
11
  import moment from './moment-shim';
11
12
  import { scaleLinear, scaleTime } from 'd3-scale';
12
13
  import { merge as _merge } from './utils';
@@ -166,6 +167,18 @@ const TimeLineInner = forwardRef<TimeLineHandle, any>(function TimeLine(props, r
166
167
 
167
168
  const patchState = useCallback((patch: any | ((s: any) => any)) => {
168
169
  setStateRaw((s: any) => ({ ...s, ...(typeof patch === 'function' ? patch(s) : patch) }));
170
+ // eslint-disable-next-line react-hooks/exhaustive-deps
171
+ }, []);
172
+
173
+ // Synchronous variant for drag/resize hot paths. React 18 normally batches
174
+ // state updates from d3-drag's native listeners to the next scheduler tick,
175
+ // so the cursor edge trails the mouse by ~1 frame. flushSync forces the
176
+ // render within the same event, matching the pre-hooks React 17 behavior
177
+ // where the cursor border tracked the pointer precisely.
178
+ const patchStateSync = useCallback((patch: any | ((s: any) => any)) => {
179
+ flushSync(() => {
180
+ setStateRaw((s: any) => ({ ...s, ...(typeof patch === 'function' ? patch(s) : patch) }));
181
+ });
169
182
  }, []);
170
183
 
171
184
  // --- Domain math --------------------------------------------------------
@@ -483,9 +496,9 @@ const TimeLineInner = forwardRef<TimeLineHandle, any>(function TimeLine(props, r
483
496
  movedSinceLastFetchedRef.current = 0;
484
497
  getItems(p, { min, max });
485
498
  }
486
- patchState({ domain: { min, max }, minTime, maxTime, ticks });
499
+ patchStateSync({ domain: { min, max }, minTime, maxTime, ticks });
487
500
  }
488
- }, [moveTimeLineCore, getItems, patchState]);
501
+ }, [moveTimeLineCore, getItems, patchStateSync]);
489
502
 
490
503
  const onResizeLeftCursor = useCallback((delta: number, mouse: any) => {
491
504
  const xAxis = xAxisRef.current;
@@ -509,10 +522,10 @@ const TimeLineInner = forwardRef<TimeLineHandle, any>(function TimeLine(props, r
509
522
  (newStop !== s.stop && newStop.isSameOrBefore(s.domain.max)) ||
510
523
  newStart.isSameOrAfter(s.domain.min)
511
524
  ) {
512
- patchState({ start: newStart, stop: newStop, maxTimespan });
525
+ patchStateSync({ start: newStart, stop: newStop, maxTimespan });
513
526
  }
514
527
  // eslint-disable-next-line react-hooks/exhaustive-deps
515
- }, [handleAutoSliding, patchState]);
528
+ }, [handleAutoSliding, patchStateSync]);
516
529
 
517
530
  const onResizeRightCursor = useCallback((delta: number, mouse: any) => {
518
531
  const xAxis = xAxisRef.current;
@@ -533,10 +546,10 @@ const TimeLineInner = forwardRef<TimeLineHandle, any>(function TimeLine(props, r
533
546
  }
534
547
  handleAutoSliding(mouse, onResizeRightCursor);
535
548
  if (newStop.isSameOrBefore(s.domain.max) && newStart.isSameOrAfter(s.domain.min)) {
536
- patchState({ start: newStart, stop: newStop, maxTimespan });
549
+ patchStateSync({ start: newStart, stop: newStop, maxTimespan });
537
550
  }
538
551
  // eslint-disable-next-line react-hooks/exhaustive-deps
539
- }, [handleAutoSliding, patchState]);
552
+ }, [handleAutoSliding, patchStateSync]);
540
553
 
541
554
  const onDragCursor = useCallback((delta: number, mouse: any) => {
542
555
  const xAxis = xAxisRef.current;
@@ -551,9 +564,9 @@ const TimeLineInner = forwardRef<TimeLineHandle, any>(function TimeLine(props, r
551
564
  if (maxDomain.min && newStart.isBefore(maxDomain.min)) newStart = moment(maxDomain.min);
552
565
  if (maxDomain.max && newStop.isAfter(maxDomain.max)) newStop = moment(maxDomain.max);
553
566
  handleAutoSliding(mouse, onDragCursor);
554
- patchState({ start: newStart, stop: newStop });
567
+ patchStateSync({ start: newStart, stop: newStop });
555
568
  // eslint-disable-next-line react-hooks/exhaustive-deps
556
- }, [handleAutoSliding, patchState]);
569
+ }, [handleAutoSliding, patchStateSync]);
557
570
 
558
571
  const onStartDrawCursor = useCallback((pos: number) => {
559
572
  const xAxis = xAxisRef.current;
@@ -583,10 +596,10 @@ const TimeLineInner = forwardRef<TimeLineHandle, any>(function TimeLine(props, r
583
596
  }
584
597
  handleAutoSliding(mouse, onDrawCursor);
585
598
  if (newStop.isSameOrBefore(s.domain.max) && newStart.isSameOrAfter(s.domain.min)) {
586
- patchState({ start: newStart, stop: newStop, maxTimespan });
599
+ patchStateSync({ start: newStart, stop: newStop, maxTimespan });
587
600
  }
588
601
  // eslint-disable-next-line react-hooks/exhaustive-deps
589
- }, [handleAutoSliding, patchState]);
602
+ }, [handleAutoSliding, patchStateSync]);
590
603
 
591
604
  const onEndDrawCursor = useCallback(() => {
592
605
  stopAutoMove();
@@ -611,6 +624,7 @@ const TimeLineInner = forwardRef<TimeLineHandle, any>(function TimeLine(props, r
611
624
  onCustomRange(start, stop);
612
625
  }, [stopAutoMove]);
613
626
 
627
+
614
628
  const zoomOnDomain = useCallback((targetDomain: any) => {
615
629
  const p = propsRef.current;
616
630
  const s = stateRef.current;
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../styles";
2
- import React from 'react';
2
+ import React, { memo } from 'react';
3
3
  import moment, { momentType } from '../moment-shim';
4
4
  import { sum as _sum } from '../utils';
5
5
  import PropTypes from 'prop-types';
@@ -7,7 +7,7 @@ import clsx from 'clsx';
7
7
  import ToolTip from '../ToolTip';
8
8
 
9
9
 
10
- export default function Histogram({
10
+ function Histogram({
11
11
  classes, items, metricsDefinition, origin,
12
12
  barHovered, tooltipVisible, verticalScale, dragging,
13
13
  HistoToolTip, onFormatMetricLegend, onFormatTimeToolTips
@@ -99,3 +99,5 @@ Histogram.propTypes = {
99
99
  barHovered: PropTypes.number,
100
100
  tooltipVisible: PropTypes.bool,
101
101
  };
102
+
103
+ export default memo(Histogram);
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { memo } from 'react';
2
2
  import moment, { momentType } from '../moment-shim';
3
3
  import PropTypes from 'prop-types';
4
4
  import {timeDay} from 'd3-time';
@@ -7,7 +7,7 @@ import clsx from 'clsx';
7
7
  import { arrow } from "./axesStyles";
8
8
  import { cn } from "../styles";
9
9
 
10
- export default function XAxis({min, max, origin, axisWidth, marks, xAxis, classes, arrowPath = arrow, onFormatTimeLegend}){
10
+ function XAxis({min, max, origin, axisWidth, marks, xAxis, classes, arrowPath = arrow, onFormatTimeLegend}){
11
11
 
12
12
  const now = moment();
13
13
 
@@ -81,3 +81,5 @@ XAxis.propTypes = {
81
81
  onFormatTimeLegend: PropTypes.func.isRequired,
82
82
  };
83
83
 
84
+ export default memo(XAxis);
85
+
@@ -1,11 +1,11 @@
1
- import React from 'react';
1
+ import React, { memo } from 'react';
2
2
  import moment from '../moment-shim';
3
3
  import PropTypes from 'prop-types';
4
4
  import clsx from 'clsx';
5
5
 
6
6
  import { cn } from "../styles";
7
7
 
8
- export default function XAxis({origin, marks, xAxis, classes, yAxisHeight}){
8
+ function XAxis({origin, marks, xAxis, classes, yAxisHeight}){
9
9
 
10
10
 
11
11
  const className = (n) => cn(n, classes);
@@ -42,3 +42,5 @@ XAxis.propTypes = {
42
42
  yAxisHeight: PropTypes.number,
43
43
  };
44
44
 
45
+ export default memo(XAxis);
46
+