You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
2.6 KiB
TypeScript
84 lines
2.6 KiB
TypeScript
import React, { useRef, useEffect, useState } from 'react';
|
|
import styles from '../Day/Day.module.scss';
|
|
import classNames from 'classnames';
|
|
import { DayVariation } from '../../../types/calendar';
|
|
|
|
interface DayNumberProps {
|
|
number: number;
|
|
proportion: number;
|
|
variations?: DayVariation[];
|
|
}
|
|
|
|
export const DayNumber: React.FC<DayNumberProps> = ({
|
|
number,
|
|
proportion,
|
|
variations = []
|
|
}) => {
|
|
const textRef = useRef<SVGTextElement>(null);
|
|
const [scale, setScale] = useState({ x: 1, y: 1 });
|
|
const isSingleDigit = number < 10;
|
|
|
|
useEffect(() => {
|
|
if (textRef.current) {
|
|
const bbox = textRef.current.getBBox();
|
|
const naturalWidth = bbox.width;
|
|
|
|
const containerWidth = 100;
|
|
const maxWidth = containerWidth * 0.8;
|
|
const baseWidth = maxWidth * (isSingleDigit ? 0.5 : 1);
|
|
const desiredWidth = baseWidth * (proportion / 100);
|
|
|
|
const scaleX = desiredWidth / naturalWidth;
|
|
const scaleY = scaleX;
|
|
|
|
setScale({ x: scaleX, y: scaleY });
|
|
}
|
|
}, [number, proportion, isSingleDigit]);
|
|
|
|
const containerClasses = classNames(
|
|
styles.DayNumber__Container,
|
|
{
|
|
[styles['DayNumber__Container--greyed']]: variations.includes('greyed'),
|
|
[styles['DayNumber__Container--selected']]: variations.includes('selected'),
|
|
[styles['DayNumber__Container--selecting']]: variations.includes('selecting'),
|
|
[styles['DayNumber__Container--rangeStart']]: variations.includes('rangeStart'),
|
|
[styles['DayNumber__Container--rangeEnd']]: variations.includes('rangeEnd'),
|
|
}
|
|
);
|
|
|
|
const textClasses = classNames(
|
|
styles.DayNumber__Text,
|
|
{
|
|
[styles['DayNumber__Text--greyed']]: variations.includes('greyed'),
|
|
[styles['DayNumber__Text--selected']]: variations.includes('selected'),
|
|
[styles['DayNumber__Text--selecting']]: variations.includes('selecting'),
|
|
[styles['DayNumber__Text--rangeStart']]: variations.includes('rangeStart'),
|
|
[styles['DayNumber__Text--rangeEnd']]: variations.includes('rangeEnd'),
|
|
}
|
|
);
|
|
|
|
return (
|
|
<div className={containerClasses}>
|
|
<svg
|
|
viewBox="0 0 100 100"
|
|
width="100%"
|
|
height="100%"
|
|
className={styles.DayNumber__Svg}
|
|
preserveAspectRatio="xMidYMid meet"
|
|
>
|
|
<text
|
|
ref={textRef}
|
|
x="50"
|
|
y="50"
|
|
textAnchor="middle"
|
|
dominantBaseline="central"
|
|
className={textClasses}
|
|
transform={`matrix(${scale.x}, 0, 0, ${scale.y}, ${50 * (1 - scale.x)}, ${50 * (1 - scale.y)})`}
|
|
>
|
|
{number}
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
);
|
|
};
|