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