Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 1x 1x 1x 12x 12x 12x 8x 12x 8x 8x 214x 12x 12x 12x 12x 10x 7x 3x 3x 26x 26x 26x 26x 3x 12x | import React from 'react';
import type {DateTime} from '@gravity-ui/date-utils';
import {dateTime} from '@gravity-ui/date-utils';
import {block} from '../../../../utils/cn';
import {getLerpCoeff} from '../../utils/span';
import {useViewportDimensions, useViewportInterval} from '../Ruler/Ruler';
import type {Geometry} from './utils';
import {
calculateTickTimes,
formatTick as defaultFormatTime,
makeMiddleTicksGeometry,
makeSlitTicksGeometry,
} from './utils';
import './Ticks.scss';
interface TicksProps {
theme: 'normal' | 'dim';
minTickWidth: number;
maxTickWidth: number;
hasLabels?: boolean;
geometry: Geometry;
className?: string;
labelsClassName?: string;
formatTime?: (time: DateTime) => string;
timeZone?: string;
}
const b = block('timeline-ticks');
export {makeMiddleTicksGeometry, makeSlitTicksGeometry};
export function Ticks({
theme,
minTickWidth,
maxTickWidth,
hasLabels,
geometry,
className,
labelsClassName,
formatTime,
timeZone,
}: TicksProps) {
const viewport = useViewportDimensions();
const interval = useViewportInterval();
const tickTimes = React.useMemo(
() =>
calculateTickTimes({
minTickWidth,
maxTickWidth,
viewportStart: interval.start,
viewportEnd: interval.end,
viewportWidth: viewport.width,
timeZone,
}),
[maxTickWidth, minTickWidth, interval, viewport.width, timeZone],
);
const tickCoords = React.useMemo(() => {
const timeToXCoeff = getLerpCoeff(
{start: interval.start.valueOf(), end: interval.end.valueOf()},
{start: 0, end: viewport.width},
);
return tickTimes.map(
(t) => 0 + Math.round((t.valueOf() - interval.start.valueOf()) * timeToXCoeff),
);
}, [tickTimes, interval, viewport.width]);
const ticksGeometry = React.useMemo(() => {
return tickCoords.map(geometry).join('');
}, [geometry, tickCoords]);
const ticksPath = <path className={b({theme}, className)} d={ticksGeometry} />;
const tickLabels = React.useMemo(() => {
if (!hasLabels || tickCoords.length < 2) {
return null;
}
const result: React.ReactElement[] = [];
for (let i = 0; i < tickCoords.length; i++) {
const x = tickCoords[i];
const t = tickTimes[i];
const dt = dateTime({input: t, timeZone});
result.push(
<text
key={i}
className={b('label', labelsClassName)}
dominantBaseline="middle"
x={x}
y="50%"
filter="url(#g-date-tt-ticklabelbg)"
>
{formatTime ? formatTime(dt) : defaultFormatTime(dt)}
</text>,
);
}
return result;
}, [hasLabels, tickCoords, tickTimes, timeZone, labelsClassName, formatTime]);
return (
<React.Fragment>
{ticksPath}
{tickLabels}
</React.Fragment>
);
}
|