export function TimelineScale()

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>
    );
}