in uui-timeline/src/TimelineScale.tsx [148:299]
export function TimelineScale({
timelineController,
isDraggable,
isScaleChangeOnWheel,
periodFont = timelineScale.defaultFonts.periodFont,
currentPeriodFont = timelineScale.defaultFonts.currentPeriodFont,
meridiemFont = timelineScale.defaultFonts.meridiemFont,
periodTextColor = timelineScale.defaultColors.periodTextColor,
bottomBorderColor = timelineScale.defaultColors.bottomBorderColor,
topDayTextColor = timelineScale.defaultColors.topDayTextColor,
weekendTextColor = timelineScale.defaultColors.weekendTextColor,
todayLineColor = timelineScale.defaultColors.todayLineColor,
todayLineHeight = timelineScale.defaultWidth.todayLineHeight,
cellBorderColor = timelineScale.defaultColors.cellBorderColor,
cellBorderWidth = timelineScale.defaultWidth.cellBorderWidth,
cellBackgroundColor = timelineScale.defaultColors.cellBackgroundColor,
evenPeriodCellBackgroundColor = timelineScale.defaultColors.evenPeriodCellBackgroundColor,
weekendCellBackgroundColor = timelineScale.defaultColors.weekendCellBackgroundColor,
getTopMonth = timelineScale.getTopMonth,
getBottomMonth = timelineScale.getBottomMonth,
drawPeriod = timelineScale.drawPeriod,
drawMinutes = timelineScale.drawMinutes,
drawRemainingHours = timelineScale.drawRemainingHours,
drawHours = timelineScale.drawHours,
drawTopDays = timelineScale.drawTopDays,
drawDays = timelineScale.drawDays,
drawTopMonths = timelineScale.drawTopMonths,
drawWeeks = timelineScale.drawWeeks,
drawBottomMonths = timelineScale.drawBottomMonths,
drawYears = timelineScale.drawYears,
drawToday = timelineScale.drawToday,
drawScaleBottomBorder = timelineScale.drawScaleBottomBorder,
...props
}: TimelineScaleProps) {
const [isMouseDown, setIsMouseDown] = useState(false);
const canvasHeight = props.canvasHeight ?? 60;
const handleWindowMouseUp = useCallback(() => {
if (isMouseDown) {
setIsMouseDown(false);
}
}, [isMouseDown, setIsMouseDown]);
const timelineTransform = useTimelineTransform({ timelineController });
const handleMouseDown = useCallback((e: React.MouseEvent<HTMLCanvasElement>) => {
timelineController.startDrag(e);
setIsMouseDown(true);
}, [timelineController]);
const handleWheel = (e: React.SyntheticEvent<HTMLCanvasElement>) => {
timelineController.handleWheelEvent(e.nativeEvent as WheelEvent);
};
const renderArrowIcon = (direction: 'left' | 'right') => {
const svg = direction === 'left' ? ArrowLeftSvg : ArrowRightSvg;
return <Svg svg={ svg } cx={ styles.arrowIcon } />;
};
const renderArrow = (direction: 'left' | 'right') => {
const handleClick = () => {
timelineController.moveBy(direction === 'left' ? -1 : 1);
};
return (
<div
className={ cx(styles.arrow, direction == 'left' ? styles.arrowLeft : styles.arrowRight) }
style={ {
height: `${canvasHeight}px`,
lineHeight: `${canvasHeight}px`,
} }
onClick={ handleClick }
>
{(props.renderArrowIcon ?? renderArrowIcon)(direction)}
</div>
);
};
const draw = (context: CanvasRenderingContext2D, t: TimelineTransform) => {
context.clearRect(0, 0, t.widthMs, canvasHeight);
const fonts = { currentPeriodFont, periodFont, meridiemFont };
const commonProps = {
context,
timelineTransform: t,
periodTextColor,
cellBackgroundColor,
canvasHeight,
...fonts,
};
const withGridLinesProps = { ...commonProps, cellBorderColor, cellBorderWidth };
const todayProps = { todayLineColor, todayLineHeight, drawToday };
drawPeriod({ ...timelineScale.getMinutesScaleRange(), draw: drawMinutes, ...withGridLinesProps });
drawPeriod({ ...timelineScale.getRemainingHoursScaleRange(), draw: drawRemainingHours, ...commonProps });
drawPeriod({ ...timelineScale.getHoursScaleRange(), draw: (...props) => drawHours(...props), ...commonProps });
drawPeriod({
draw: (props) => drawTopDays({ ...props, topDayTextColor, weekendTextColor, weekendCellBackgroundColor, getTopMonth, ...todayProps }),
...timelineScale.getTopDaysScaleRange(),
...withGridLinesProps,
});
drawPeriod({
draw: (props) => drawDays({ ...props, weekendTextColor, weekendCellBackgroundColor, ...todayProps }),
...timelineScale.getDaysScaleRange(),
...withGridLinesProps,
});
drawPeriod({
draw: (props) => drawTopMonths({ ...props, evenPeriodCellBackgroundColor, getTopMonth }),
...timelineScale.getTopMonthsScaleRange(),
...withGridLinesProps,
});
drawPeriod({
draw: (props) => drawWeeks({ ...props, drawToday, ...todayProps }),
...timelineScale.getWeeksScaleRange(),
...withGridLinesProps,
});
drawPeriod({
draw: (props) => drawBottomMonths({ ...props, getBottomMonth, drawToday, ...todayProps }),
...timelineScale.getBottomMonthsScaleRange(),
...withGridLinesProps });
drawPeriod({
draw: (props) => drawYears({ ...props, drawToday, evenPeriodCellBackgroundColor, ...todayProps }),
...timelineScale.getYearsScaleRange(),
...withGridLinesProps,
});
drawScaleBottomBorder({ context, canvasHeight, timelineTransform: t, bottomBorderColor });
};
useEffect(() => {
window.addEventListener('mouseup', handleWindowMouseUp);
return () => {
window.removeEventListener('mouseup', handleWindowMouseUp);
};
}, [handleWindowMouseUp]);
return (
<div className={ styles.timelineHeader } style={ { width: timelineTransform.widthPx, height: `${canvasHeight}px` } }>
{!isMouseDown && (props.renderArrow ?? renderArrow)('left')}
{!isMouseDown && (props.renderArrow ?? renderArrow)('right')}
<TimelineCanvas
className={ isMouseDown ? styles.timelineScaleGrabbing : styles.timelineScale }
onMouseDown={ isDraggable && handleMouseDown }
onWheel={ isScaleChangeOnWheel && handleWheel }
draw={ props.draw ?? draw }
canvasHeight={ canvasHeight }
timelineController={ timelineController }
/>
</div>
);
}