@spider-analyzer/timeline 5.0.6 → 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/CHANGELOG.md +36 -0
- package/dist/index.js +61 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +62 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Cursor.jsx +3 -3
- package/src/TimeLine.tsx +36 -13
- package/src/cursorElements/CursorSelection.jsx +3 -3
- package/src/cursorElements/DragOverlay.jsx +3 -3
- package/src/moment-shim.ts +25 -0
- package/src/timeLineElements/HistoToolTip.jsx +3 -3
- package/src/timeLineElements/Histogram.jsx +7 -5
- package/src/timeLineElements/QualityLine.jsx +2 -2
- package/src/timeLineElements/XAxis.jsx +7 -5
- package/src/timeLineElements/XGrid.jsx +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
## 5.0.9
|
|
2
|
+
|
|
3
|
+
- Perf: cursor edge now tracks the pointer during drag/resize/draw, as
|
|
4
|
+
it did in the pre-hooks class component. Drag/resize hot paths
|
|
5
|
+
(`moveTimeLine`, `onDragCursor`, `onResizeLeftCursor`,
|
|
6
|
+
`onResizeRightCursor`, `onDrawCursor`) commit state via a
|
|
7
|
+
`flushSync`-wrapped `patchStateSync`. React 18 otherwise batches
|
|
8
|
+
updates from d3-drag's native listeners to its scheduler, adding ~1
|
|
9
|
+
frame of latency between pointer and cursor border. Also wrapped
|
|
10
|
+
`Histogram`, `XAxis`, `XGrid` in `React.memo` so the synchronous
|
|
11
|
+
per-event render only reconciles the Cursor subtree; heavy
|
|
12
|
+
histogram/axis/grid trees are skipped when only `start`/`stop`
|
|
13
|
+
change.
|
|
14
|
+
|
|
15
|
+
## 5.0.8
|
|
16
|
+
|
|
17
|
+
- Perf: memoize the per-render histogram bar list and vertical scale.
|
|
18
|
+
Previously every cursor drag / resize / draw event (60×/sec) rebuilt
|
|
19
|
+
the entire bar list (~550 bars in Network-View's default view) from
|
|
20
|
+
scratch. Under the Luxon-backed shim each rebuild allocated 550 new
|
|
21
|
+
DateTime/MomentLike objects and re-ran d3's time scale — ~150 ms per
|
|
22
|
+
render, i.e. ≈6 fps drag. Wrap `prepareHistogram` and
|
|
23
|
+
`prepareVerticalScale` with `useMemo` keyed on the actual dependencies
|
|
24
|
+
(`domain`, `histoWidth`, `histo`) so they only recompute when those
|
|
25
|
+
change. Cursor drag returns to single-digit-ms render time.
|
|
26
|
+
|
|
27
|
+
## 5.0.7
|
|
28
|
+
|
|
29
|
+
- Fix: silence the `Invalid prop 'time' of type '_MomentLike', expected
|
|
30
|
+
instance of 'moment2'` React warnings that internal components
|
|
31
|
+
(Histogram, Cursor, XAxis, QualityLine, DragOverlay, CursorSelection,
|
|
32
|
+
HistoToolTip) emitted under every render. The Luxon-backed moment
|
|
33
|
+
shim is a factory function, not a class, so `PropTypes.instanceOf` is
|
|
34
|
+
the wrong check. Replaced with a `momentType` validator that uses
|
|
35
|
+
`moment.isMoment()`. No runtime behavior change — warnings only.
|
|
36
|
+
|
|
1
37
|
## 5.0.6
|
|
2
38
|
|
|
3
39
|
- Fix: don't issue the first `onLoadHisto` with a stale `intervalMs`
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var react = require('react');
|
|
6
|
+
var reactDom = require('react-dom');
|
|
6
7
|
var luxon = require('luxon');
|
|
7
8
|
var d3Scale = require('d3-scale');
|
|
8
9
|
var PropTypes11 = require('prop-types');
|
|
@@ -172,6 +173,25 @@ moment.tz = (x, zone) => {
|
|
|
172
173
|
const base = toDT(x);
|
|
173
174
|
return new MomentLike(base.setZone(zone));
|
|
174
175
|
};
|
|
176
|
+
function validate(props, propName, componentName) {
|
|
177
|
+
const v = props[propName];
|
|
178
|
+
if (v == null) return null;
|
|
179
|
+
if (moment.isMoment(v)) return null;
|
|
180
|
+
return new Error(
|
|
181
|
+
`Invalid prop \`${propName}\` supplied to \`${componentName}\`, expected a moment-like object.`
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
var required = (props, propName, componentName) => {
|
|
185
|
+
const v = props[propName];
|
|
186
|
+
if (v == null) {
|
|
187
|
+
return new Error(
|
|
188
|
+
`The prop \`${propName}\` is marked as required in \`${componentName}\`, but its value is \`${v}\`.`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
return validate(props, propName, componentName);
|
|
192
|
+
};
|
|
193
|
+
var momentType = validate;
|
|
194
|
+
momentType.isRequired = required;
|
|
175
195
|
var moment_shim_default = moment;
|
|
176
196
|
|
|
177
197
|
// src/utils.ts
|
|
@@ -375,8 +395,8 @@ DragOverlay.propTypes = {
|
|
|
375
395
|
width: PropTypes11__default.default.number.isRequired,
|
|
376
396
|
marginBottom: PropTypes11__default.default.number,
|
|
377
397
|
items: PropTypes11__default.default.arrayOf(PropTypes11__default.default.shape({
|
|
378
|
-
start:
|
|
379
|
-
end:
|
|
398
|
+
start: momentType.isRequired,
|
|
399
|
+
end: momentType.isRequired,
|
|
380
400
|
x1: PropTypes11__default.default.number,
|
|
381
401
|
x2: PropTypes11__default.default.number,
|
|
382
402
|
metrics: PropTypes11__default.default.arrayOf(PropTypes11__default.default.number).isRequired,
|
|
@@ -686,8 +706,8 @@ CursorSelection.propTypes = {
|
|
|
686
706
|
showToolTipLeft: PropTypes11__default.default.func.isRequired,
|
|
687
707
|
showToolTipRight: PropTypes11__default.default.func.isRequired,
|
|
688
708
|
items: PropTypes11__default.default.arrayOf(PropTypes11__default.default.shape({
|
|
689
|
-
start:
|
|
690
|
-
end:
|
|
709
|
+
start: momentType.isRequired,
|
|
710
|
+
end: momentType.isRequired,
|
|
691
711
|
x1: PropTypes11__default.default.number,
|
|
692
712
|
x2: PropTypes11__default.default.number,
|
|
693
713
|
metrics: PropTypes11__default.default.arrayOf(PropTypes11__default.default.number).isRequired,
|
|
@@ -1273,8 +1293,8 @@ Cursor.propTypes = {
|
|
|
1273
1293
|
overlayHeight: PropTypes11__default.default.number.isRequired,
|
|
1274
1294
|
overlayWidth: PropTypes11__default.default.number.isRequired,
|
|
1275
1295
|
items: PropTypes11__default.default.arrayOf(PropTypes11__default.default.shape({
|
|
1276
|
-
start:
|
|
1277
|
-
end:
|
|
1296
|
+
start: momentType.isRequired,
|
|
1297
|
+
end: momentType.isRequired,
|
|
1278
1298
|
x1: PropTypes11__default.default.number,
|
|
1279
1299
|
x2: PropTypes11__default.default.number,
|
|
1280
1300
|
metrics: PropTypes11__default.default.arrayOf(PropTypes11__default.default.number).isRequired,
|
|
@@ -1383,8 +1403,8 @@ function Histogram({
|
|
|
1383
1403
|
Histogram.propTypes = {
|
|
1384
1404
|
classes: PropTypes11__default.default.object,
|
|
1385
1405
|
items: PropTypes11__default.default.arrayOf(PropTypes11__default.default.shape({
|
|
1386
|
-
start:
|
|
1387
|
-
end:
|
|
1406
|
+
start: momentType.isRequired,
|
|
1407
|
+
end: momentType.isRequired,
|
|
1388
1408
|
x1: PropTypes11__default.default.number,
|
|
1389
1409
|
x2: PropTypes11__default.default.number,
|
|
1390
1410
|
metrics: PropTypes11__default.default.arrayOf(PropTypes11__default.default.number).isRequired,
|
|
@@ -1410,6 +1430,7 @@ Histogram.propTypes = {
|
|
|
1410
1430
|
barHovered: PropTypes11__default.default.number,
|
|
1411
1431
|
tooltipVisible: PropTypes11__default.default.bool
|
|
1412
1432
|
};
|
|
1433
|
+
var Histogram_default = react.memo(Histogram);
|
|
1413
1434
|
|
|
1414
1435
|
// src/timeLineElements/axesStyles.jsx
|
|
1415
1436
|
var arrow = `m 0,-5 5,5 -5,5`;
|
|
@@ -1484,8 +1505,8 @@ function XAxis({ min, max: max2, origin, axisWidth, marks, xAxis, classes, arrow
|
|
|
1484
1505
|
XAxis.propTypes = {
|
|
1485
1506
|
axisWidth: PropTypes11__default.default.number.isRequired,
|
|
1486
1507
|
classes: PropTypes11__default.default.object,
|
|
1487
|
-
min:
|
|
1488
|
-
max:
|
|
1508
|
+
min: momentType,
|
|
1509
|
+
max: momentType,
|
|
1489
1510
|
origin: PropTypes11__default.default.shape({
|
|
1490
1511
|
x: PropTypes11__default.default.number.isRequired,
|
|
1491
1512
|
y: PropTypes11__default.default.number.isRequired
|
|
@@ -1495,6 +1516,7 @@ XAxis.propTypes = {
|
|
|
1495
1516
|
arrowPath: PropTypes11__default.default.string,
|
|
1496
1517
|
onFormatTimeLegend: PropTypes11__default.default.func.isRequired
|
|
1497
1518
|
};
|
|
1519
|
+
var XAxis_default = react.memo(XAxis);
|
|
1498
1520
|
function YAxis({ classes, marks, yAxis, onFormatMetricLegend, maxHeight, origin, arrowPath = arrow }) {
|
|
1499
1521
|
const className = (n) => cn(n, classes);
|
|
1500
1522
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -1810,8 +1832,8 @@ function HistoTooltip({ metricsDefinition, item, onFormatTimeToolTips, onFormatM
|
|
|
1810
1832
|
HistoTooltip.propTypes = {
|
|
1811
1833
|
classes: PropTypes11__default.default.object,
|
|
1812
1834
|
item: PropTypes11__default.default.shape({
|
|
1813
|
-
start:
|
|
1814
|
-
end:
|
|
1835
|
+
start: momentType.isRequired,
|
|
1836
|
+
end: momentType.isRequired,
|
|
1815
1837
|
x1: PropTypes11__default.default.number,
|
|
1816
1838
|
x2: PropTypes11__default.default.number,
|
|
1817
1839
|
metrics: PropTypes11__default.default.arrayOf(PropTypes11__default.default.number).isRequired,
|
|
@@ -1879,7 +1901,7 @@ QualityLine.propTypes = {
|
|
|
1879
1901
|
xAxis: PropTypes11__default.default.func.isRequired,
|
|
1880
1902
|
quality: PropTypes11__default.default.shape({
|
|
1881
1903
|
items: PropTypes11__default.default.arrayOf(PropTypes11__default.default.shape({
|
|
1882
|
-
time:
|
|
1904
|
+
time: momentType.isRequired,
|
|
1883
1905
|
quality: PropTypes11__default.default.number.isRequired,
|
|
1884
1906
|
tip: PropTypes11__default.default.node
|
|
1885
1907
|
})),
|
|
@@ -1949,6 +1971,7 @@ XAxis2.propTypes = {
|
|
|
1949
1971
|
xAxis: PropTypes11__default.default.func,
|
|
1950
1972
|
yAxisHeight: PropTypes11__default.default.number
|
|
1951
1973
|
};
|
|
1974
|
+
var XGrid_default = react.memo(XAxis2);
|
|
1952
1975
|
|
|
1953
1976
|
// src/time.ts
|
|
1954
1977
|
function toMoment(x, zone) {
|
|
@@ -1971,8 +1994,8 @@ function timeSpanToMoments(t, zone) {
|
|
|
1971
1994
|
return { start: toMomentOpt(t.start, zone), stop: toMomentOpt(t.stop, zone) };
|
|
1972
1995
|
}
|
|
1973
1996
|
var Cursor2 = Cursor;
|
|
1974
|
-
var Histogram2 =
|
|
1975
|
-
var XAxis3 =
|
|
1997
|
+
var Histogram2 = Histogram_default;
|
|
1998
|
+
var XAxis3 = XAxis_default;
|
|
1976
1999
|
var YAxis3 = YAxis;
|
|
1977
2000
|
var Legend2 = Legend;
|
|
1978
2001
|
var Tools2 = Tools;
|
|
@@ -2067,6 +2090,11 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2067
2090
|
const patchState = react.useCallback((patch) => {
|
|
2068
2091
|
setStateRaw((s) => ({ ...s, ...typeof patch === "function" ? patch(s) : patch }));
|
|
2069
2092
|
}, []);
|
|
2093
|
+
const patchStateSync = react.useCallback((patch) => {
|
|
2094
|
+
reactDom.flushSync(() => {
|
|
2095
|
+
setStateRaw((s) => ({ ...s, ...typeof patch === "function" ? patch(s) : patch }));
|
|
2096
|
+
});
|
|
2097
|
+
}, []);
|
|
2070
2098
|
const checkAndCorrectDomain = react.useCallback(({ domain: domain2 }) => {
|
|
2071
2099
|
return checkAndCorrectDomainPure({
|
|
2072
2100
|
domain: domain2,
|
|
@@ -2310,9 +2338,9 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2310
2338
|
movedSinceLastFetchedRef.current = 0;
|
|
2311
2339
|
getItems(p, { min, max: max2 });
|
|
2312
2340
|
}
|
|
2313
|
-
|
|
2341
|
+
patchStateSync({ domain: { min, max: max2 }, minTime, maxTime, ticks: ticks2 });
|
|
2314
2342
|
}
|
|
2315
|
-
}, [moveTimeLineCore, getItems,
|
|
2343
|
+
}, [moveTimeLineCore, getItems, patchStateSync]);
|
|
2316
2344
|
const onResizeLeftCursor = react.useCallback((delta, mouse) => {
|
|
2317
2345
|
const xAxis = xAxisRef.current;
|
|
2318
2346
|
const s = stateRef.current;
|
|
@@ -2332,9 +2360,9 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2332
2360
|
}
|
|
2333
2361
|
handleAutoSliding(mouse, onResizeLeftCursor);
|
|
2334
2362
|
if (newStop !== s.stop && newStop.isSameOrBefore(s.domain.max) || newStart.isSameOrAfter(s.domain.min)) {
|
|
2335
|
-
|
|
2363
|
+
patchStateSync({ start: newStart, stop: newStop, maxTimespan: maxTimespan2 });
|
|
2336
2364
|
}
|
|
2337
|
-
}, [handleAutoSliding,
|
|
2365
|
+
}, [handleAutoSliding, patchStateSync]);
|
|
2338
2366
|
const onResizeRightCursor = react.useCallback((delta, mouse) => {
|
|
2339
2367
|
const xAxis = xAxisRef.current;
|
|
2340
2368
|
const s = stateRef.current;
|
|
@@ -2354,9 +2382,9 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2354
2382
|
}
|
|
2355
2383
|
handleAutoSliding(mouse, onResizeRightCursor);
|
|
2356
2384
|
if (newStop.isSameOrBefore(s.domain.max) && newStart.isSameOrAfter(s.domain.min)) {
|
|
2357
|
-
|
|
2385
|
+
patchStateSync({ start: newStart, stop: newStop, maxTimespan: maxTimespan2 });
|
|
2358
2386
|
}
|
|
2359
|
-
}, [handleAutoSliding,
|
|
2387
|
+
}, [handleAutoSliding, patchStateSync]);
|
|
2360
2388
|
const onDragCursor = react.useCallback((delta, mouse) => {
|
|
2361
2389
|
const xAxis = xAxisRef.current;
|
|
2362
2390
|
const s = stateRef.current;
|
|
@@ -2370,8 +2398,8 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2370
2398
|
if (maxDomain.min && newStart.isBefore(maxDomain.min)) newStart = moment_shim_default(maxDomain.min);
|
|
2371
2399
|
if (maxDomain.max && newStop.isAfter(maxDomain.max)) newStop = moment_shim_default(maxDomain.max);
|
|
2372
2400
|
handleAutoSliding(mouse, onDragCursor);
|
|
2373
|
-
|
|
2374
|
-
}, [handleAutoSliding,
|
|
2401
|
+
patchStateSync({ start: newStart, stop: newStop });
|
|
2402
|
+
}, [handleAutoSliding, patchStateSync]);
|
|
2375
2403
|
const onStartDrawCursor = react.useCallback((pos) => {
|
|
2376
2404
|
const xAxis = xAxisRef.current;
|
|
2377
2405
|
patchState({
|
|
@@ -2399,9 +2427,9 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2399
2427
|
}
|
|
2400
2428
|
handleAutoSliding(mouse, onDrawCursor);
|
|
2401
2429
|
if (newStop.isSameOrBefore(s.domain.max) && newStart.isSameOrAfter(s.domain.min)) {
|
|
2402
|
-
|
|
2430
|
+
patchStateSync({ start: newStart, stop: newStop, maxTimespan: maxTimespan2 });
|
|
2403
2431
|
}
|
|
2404
|
-
}, [handleAutoSliding,
|
|
2432
|
+
}, [handleAutoSliding, patchStateSync]);
|
|
2405
2433
|
const onEndDrawCursor = react.useCallback(() => {
|
|
2406
2434
|
stopAutoMove();
|
|
2407
2435
|
const { onCustomRange, selectBarOnClick } = propsRef.current;
|
|
@@ -2564,13 +2592,17 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2564
2592
|
ticks,
|
|
2565
2593
|
dragging
|
|
2566
2594
|
} = state;
|
|
2595
|
+
const verticalScaleData = react.useMemo(() => prepareVerticalScale(), [prepareVerticalScale]);
|
|
2596
|
+
const items = react.useMemo(
|
|
2597
|
+
() => prepareHistogram({ domain, verticalScale: verticalScaleData.verticalScale }),
|
|
2598
|
+
[prepareHistogram, domain, verticalScaleData, histoWidth]
|
|
2599
|
+
);
|
|
2600
|
+
itemsRef.current = items;
|
|
2567
2601
|
const xAxisHeight = xAxisProp.height || xAxisDefault.height;
|
|
2568
2602
|
const pointZero = { x: 0, y: height - margin.bottom - xAxisHeight };
|
|
2569
2603
|
const originCursor = { x: 0, y: margin.top - 5 };
|
|
2570
2604
|
if (!isFunction(xAxisRef.current)) return null;
|
|
2571
|
-
const { verticalScale, verticalMarks, maxHeight } =
|
|
2572
|
-
const items = prepareHistogram({ domain, verticalScale });
|
|
2573
|
-
itemsRef.current = items;
|
|
2605
|
+
const { verticalScale, verticalMarks, maxHeight } = verticalScaleData;
|
|
2574
2606
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2575
2607
|
"svg",
|
|
2576
2608
|
{
|
|
@@ -2590,7 +2622,7 @@ var TimeLineInner = react.forwardRef(function TimeLine(props, ref) {
|
|
|
2590
2622
|
}
|
|
2591
2623
|
),
|
|
2592
2624
|
xAxisProp.showGrid && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2593
|
-
|
|
2625
|
+
XGrid_default,
|
|
2594
2626
|
{
|
|
2595
2627
|
classes,
|
|
2596
2628
|
origin: pointZero,
|