feat: DateRange example
parent
bc2c3b5474
commit
c22918d3ea
@ -0,0 +1,46 @@
|
|||||||
|
@use '../shared/variables' as shared;
|
||||||
|
@use '../shared/colors' as colors;
|
||||||
|
|
||||||
|
.DateRange {
|
||||||
|
&__Container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__DayWrapper {
|
||||||
|
padding: shared.$week-wrapper-padding;
|
||||||
|
|
||||||
|
@media (min-width: shared.$breakpoint-tablet) {
|
||||||
|
padding: shared.$week-wrapper-padding-desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--rangeStart:not(&--rangeEnd) {
|
||||||
|
padding: shared.$week-wrapper-padding 0 shared.$week-wrapper-padding shared.$week-wrapper-padding;
|
||||||
|
background-color: colors.$day-color-selected;
|
||||||
|
|
||||||
|
@media (min-width: shared.$breakpoint-tablet) {
|
||||||
|
padding: shared.$week-wrapper-padding-desktop 0 shared.$week-wrapper-padding-desktop shared.$week-wrapper-padding-desktop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--rangeEnd:not(&--rangeStart) {
|
||||||
|
padding: shared.$week-wrapper-padding shared.$week-wrapper-padding shared.$week-wrapper-padding 0;
|
||||||
|
background-color: colors.$day-color-selected;
|
||||||
|
|
||||||
|
@media (min-width: shared.$breakpoint-tablet) {
|
||||||
|
padding: shared.$week-wrapper-padding-desktop shared.$week-wrapper-padding-desktop shared.$week-wrapper-padding-desktop 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--selected:not(&--rangeStart):not(&--rangeEnd) {
|
||||||
|
padding: shared.$week-wrapper-padding 0;
|
||||||
|
background-color: colors.$day-color-selected;
|
||||||
|
|
||||||
|
@media (min-width: shared.$breakpoint-tablet) {
|
||||||
|
padding: shared.$week-wrapper-padding-desktop 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { eachDayOfInterval, startOfDay } from 'date-fns';
|
||||||
|
import { Day } from '../Day';
|
||||||
|
import { getDateVariations } from '../../../utils/dateUtils';
|
||||||
|
import { HeaderStyle, DaySize } from '../../../types/calendar';
|
||||||
|
import styles from './DateRange.module.scss';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface DateRangeProps {
|
||||||
|
from: Date;
|
||||||
|
to: Date;
|
||||||
|
included?: boolean;
|
||||||
|
headerStyle?: HeaderStyle;
|
||||||
|
weekendDays?: number[];
|
||||||
|
size?: DaySize;
|
||||||
|
fontProportion?: number;
|
||||||
|
magnify?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DateRange: React.FC<DateRangeProps> = ({
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
included = true,
|
||||||
|
headerStyle = 'tiny',
|
||||||
|
weekendDays = [6, 0],
|
||||||
|
size = 'l',
|
||||||
|
fontProportion = 100,
|
||||||
|
magnify = false
|
||||||
|
}) => {
|
||||||
|
const startDate = startOfDay(from);
|
||||||
|
const endDate = startOfDay(to);
|
||||||
|
|
||||||
|
const days = eachDayOfInterval({ start: startDate, end: endDate });
|
||||||
|
|
||||||
|
const dateRange = included ? {
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
selecting: false,
|
||||||
|
hoverDate: null,
|
||||||
|
anchorDate: null
|
||||||
|
} : undefined;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.DateRange__Container}>
|
||||||
|
{days.map((date, i) => {
|
||||||
|
const dayOfWeek = date.getDay();
|
||||||
|
const variations = getDateVariations(date, dateRange, weekendDays, dayOfWeek);
|
||||||
|
|
||||||
|
const wrapperClasses = classNames(
|
||||||
|
styles.DateRange__DayWrapper,
|
||||||
|
{
|
||||||
|
[styles['DateRange__DayWrapper--rangeStart']]: variations.includes('rangeStart'),
|
||||||
|
[styles['DateRange__DayWrapper--rangeEnd']]: variations.includes('rangeEnd'),
|
||||||
|
[styles['DateRange__DayWrapper--selected']]: variations.includes('selected'),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={wrapperClasses} key={date.toISOString()}>
|
||||||
|
<Day
|
||||||
|
date={date}
|
||||||
|
headerStyle={headerStyle}
|
||||||
|
variations={variations}
|
||||||
|
size={size}
|
||||||
|
fontProportion={fontProportion}
|
||||||
|
magnify={magnify}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { DateRange } from '../components/calendar/DateRange';
|
||||||
|
import { Controls } from '../components/calendar/Controls';
|
||||||
|
import { HeaderStyle, DaySize, MonthCutoffType } from '../types/calendar';
|
||||||
|
import styles from './Examples.module.scss';
|
||||||
|
|
||||||
|
export const DateRangeView: React.FC = () => {
|
||||||
|
const [dayHeaderStyle, setDayHeaderStyle] = useState<HeaderStyle>('tiny');
|
||||||
|
const [size, setSize] = useState<DaySize>('l');
|
||||||
|
const [fontProportion, setFontProportion] = useState<number>(100);
|
||||||
|
const [included, setIncluded] = useState<boolean>(true);
|
||||||
|
const [monthCutoff, setMonthCutoff] = useState<MonthCutoffType>(undefined);
|
||||||
|
|
||||||
|
const fromDate = new Date(2025, 0, 15); // January 15, 2025
|
||||||
|
const toDate = new Date(2025, 0, 22); // January 22, 2025
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className={styles.section}>
|
||||||
|
<h2 className={styles.sectionTitle}>Date Range View</h2>
|
||||||
|
<p className={styles.sectionDescription}>
|
||||||
|
Display a custom date range with optional selection highlighting.
|
||||||
|
</p>
|
||||||
|
<Controls
|
||||||
|
headerStyle={dayHeaderStyle}
|
||||||
|
monthCutoff={monthCutoff}
|
||||||
|
size={size}
|
||||||
|
fontProportion={fontProportion}
|
||||||
|
onHeaderStyleChange={setDayHeaderStyle}
|
||||||
|
onMonthCutoffChange={setMonthCutoff}
|
||||||
|
onSizeChange={setSize}
|
||||||
|
onFontProportionChange={setFontProportion}
|
||||||
|
/>
|
||||||
|
<div className={styles.controlRow}>
|
||||||
|
<label className={styles.control}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={included}
|
||||||
|
onChange={(e) => setIncluded(e.target.checked)}
|
||||||
|
/>
|
||||||
|
<span>Show as selected range</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className={styles.demoContainer}>
|
||||||
|
<DateRange
|
||||||
|
from={fromDate}
|
||||||
|
to={toDate}
|
||||||
|
included={included}
|
||||||
|
headerStyle={dayHeaderStyle}
|
||||||
|
weekendDays={[6, 0]}
|
||||||
|
size={size}
|
||||||
|
fontProportion={fontProportion}
|
||||||
|
magnify={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.codeExample}>
|
||||||
|
<pre>{`<DateRange
|
||||||
|
from={new Date(2025, 0, 15)}
|
||||||
|
to={new Date(2025, 0, 22)}
|
||||||
|
included={${included}}
|
||||||
|
headerStyle="${dayHeaderStyle}"
|
||||||
|
size="${size}"
|
||||||
|
fontProportion={${fontProportion}}
|
||||||
|
magnify={true}
|
||||||
|
/>`}</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue