Skip to content

Commit de315cf

Browse files
committed
Update UI for selecting month/year
1 parent fd75f77 commit de315cf

23 files changed

+489
-414
lines changed

src/calendar/calendar.css

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,38 @@
33
color: #dddddd !important;
44
}
55
.calendar-container {
6+
--border-radius: 0.3em;
67
min-width: fit-content;
7-
width: 320px;
8-
height: 380px;
8+
width: fit-content;
9+
height: fit-content;
910
box-sizing: border-box;
10-
/* position: absolute; */
1111
display: flex;
1212
flex-direction: column;
1313
padding: 0.7em;
1414
background-color: #ffffff;
1515
box-shadow: 0 0 4px 0px #00000040;
16-
border-radius: 0.3em;
16+
border-radius: var(--border-radius);
17+
18+
--background: #fff;
19+
--color: rgb(32, 32, 32);
20+
--weekend-background: rgb(66, 141, 129);
21+
--weekend-color: rgb(175, 76, 76);
22+
--selected-background: var(--weekend-color);
23+
--selected-color: #fff;
24+
--today-background: var(--weekend-color);
25+
--today-color: rgb(160, 80, 80);
26+
--disabled-background: rgb(201, 201, 201);
27+
--disabled-color: rgb(226, 226, 226);
28+
--offmonth-background: #fff;
29+
--offmonth-color: rgb(184, 184, 184);
30+
--header-background: #fff;
31+
--header-color: #fff;
32+
--week-days-background: #fff;
33+
--week-days-color: #fff;
34+
35+
--day-radius: 0;
1736
}
37+
1838
.calendar-inner {
1939
position: absolute;
2040
top: 0;

src/calendar/calendar.tsx

Lines changed: 27 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,56 @@
11
import React, { useContext, useState } from 'react';
2+
import { Predicate } from '../types';
3+
import { CalendarStateContext } from '../picker/picker';
4+
import { SelectedContext } from '../context/selectedContext'
25
import MonthComponent from '../month/month';
3-
import YearComponent from '../year/year';
46
import Header from '../header/header';
5-
import Years from '../years/years';
6-
import { CalendarStateContext, SelectedDateContext } from '../context'
7-
import { Predicate } from '../types';
7+
import CalendarContextProvider from '../context/calendarContext'
8+
import Options from '../options';
89
import './calendar.css'
910

1011
type CalendarProps = { className?: string, style?: React.CSSProperties, initial?: Date, selected?: Date | undefined, predicate?: Predicate<Date>, locale?: string, onDateSelected?: (date: Date) => void }
1112
type CalendarState = { index: number, selected: Date | undefined, calendar: Date }
1213

13-
function getToday(): Date {
14-
const date = new Date()
15-
date.setHours(0)
16-
date.setMinutes(0)
17-
date.setSeconds(0)
18-
date.setMilliseconds(0)
1914

20-
return date
21-
}
15+
export default ({ className = "", style, initial, locale, predicate = () => false, onDateSelected }: CalendarProps) => {
16+
let [calendarState, setCalendarState] = useContext(CalendarStateContext)
17+
const [selected, setSelected] = useContext(SelectedContext)
18+
const [showOptions, setShowOptions] = useState(false)
2219

23-
function Calendar({ className = "", style, initial = getToday(), locale, predicate = () => false, onDateSelected }: CalendarProps) {
24-
const { value, action } = useContext(SelectedDateContext)
25-
const calendarStateContext = useContext(CalendarStateContext)
26-
const [index, setIndex] = useState(0)
27-
const [calendar, setCalendar] = useState(value ? new Date(value) : initial)
2820

29-
const today = getToday()
30-
let lossFocusHandler: { (e: MouseEvent): void }
3121
return (
32-
<div ref={setCalendarContainer} className={`${className} calendar-container`} style={style} >
33-
<Header
34-
index={index}
35-
calendar={calendar}
36-
onChange={(date: Date) => { setCalendar(date) }}
37-
onClick={(e: React.MouseEvent<HTMLDivElement, MouseEvent>, index) => {
38-
setIndex(index)
39-
40-
}} />
41-
{
42-
index === 0 && (
43-
<MonthComponent
44-
calendar={calendar}
45-
selected={value}
46-
today={today}
47-
predicate={predicate}
48-
onClick={(e: React.MouseEvent<HTMLDivElement, MouseEvent>, time) => {
49-
action(new Date(time))
50-
onDateSelected && onDateSelected(value as Date)
51-
calendarStateContext.action(false)
52-
}} />
53-
)
54-
}
55-
{
56-
index === 1 && (
57-
<YearComponent calendar={calendar} today={today} selected={value} predicate={predicate} onClick={(e: React.MouseEvent<HTMLDivElement, MouseEvent>, month: number) => {
58-
calendar.setMonth(month);
59-
setCalendar(calendar)
60-
setIndex(0)
61-
e.nativeEvent.stopImmediatePropagation()
22+
<CalendarContextProvider initial={initial || selected}>
23+
<div ref={setCalendarContainer} className={`${className} calendar-container`} style={style} >
24+
<Header onAction={() => { setShowOptions(true) }} />
25+
<MonthComponent
26+
predicate={predicate}
27+
onClick={(e: React.MouseEvent<HTMLDivElement, MouseEvent>, time) => {
28+
setSelected?.(new Date(time))
29+
onDateSelected?.(selected)
30+
setCalendarState?.(false)
6231
}} />
63-
)
64-
}
65-
{
66-
index === 2 && (
67-
<Years
68-
calendar={calendar}
69-
predicate={predicate}
70-
onClick={(e: React.MouseEvent<HTMLDivElement, MouseEvent>, value: number) => {
71-
calendar.setFullYear(value);
72-
setCalendar(calendar)
73-
setIndex(1)
74-
e.nativeEvent.stopImmediatePropagation()
75-
}} />
76-
)
77-
}
78-
</div>
32+
{showOptions && <Options onAction={() => { setShowOptions(false) }}></Options>}
33+
</div>
34+
</CalendarContextProvider>
7935
)
8036

8137
function setCalendarContainer(element: HTMLDivElement) {
38+
let lossFocusHandler: { (e: MouseEvent): void } | undefined = undefined
39+
8240
if (element) {
8341
lossFocusHandler = (e: MouseEvent) => {
8442
let target: Element | null = e.target as Element
8543
while (target) {
8644
if (target === element) return
8745
target = target.parentElement
8846
}
89-
document.removeEventListener('click', lossFocusHandler)
90-
calendarStateContext.action(false)
47+
setCalendarState?.(false)
48+
lossFocusHandler && document.removeEventListener('click', lossFocusHandler)
9149
}
9250
document.addEventListener('click', lossFocusHandler)
9351
} else {
94-
document.removeEventListener('click', lossFocusHandler)
52+
lossFocusHandler && document.removeEventListener('click', lossFocusHandler)
9553

9654
}
9755
}
98-
99-
100-
101-
102-
}
103-
104-
export default Calendar
56+
}

src/context.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/context/calendarContext.jsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React, { createContext, useState } from "react";
2+
3+
export const CalendarContext = createContext();
4+
5+
export default (props) => {
6+
const calendarState = useState(props?.initial ?? new Date());
7+
8+
return (
9+
<CalendarContext.Provider value={calendarState}>
10+
{props.children}
11+
</CalendarContext.Provider>
12+
);
13+
};

src/context/selectedContext.jsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React, { createContext, useState } from "react";
2+
3+
export const SelectedContext = createContext();
4+
5+
export default ({ selected, children }) => {
6+
const selectedState = useState(selected);
7+
8+
return (
9+
<SelectedContext.Provider value={selectedState}>
10+
{children}
11+
</SelectedContext.Provider>
12+
);
13+
};

src/day/day.css

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,54 @@
1-
2-
.day-container {
3-
display: inline-flex;
4-
justify-content: center;
5-
align-items: center;
6-
cursor: pointer;
7-
border-radius: .2em;
8-
width: 34px;
9-
height: 34px;
10-
line-height: 34px;
11-
text-align: center;
12-
box-sizing: border-box;
13-
transition: background-color .3s;
14-
}
15-
16-
.day-container:hover {
17-
background-color: rgba(0, 0, 0, 0.072);
18-
transition: background-color .3s;
19-
}
20-
.today {
21-
box-shadow: 0 0 0 0.1em #66abba;
22-
color: #66abba;
23-
}
24-
.today:hover {
25-
box-shadow: 0 0 0 0.1em #66aaba91;
26-
}
27-
.today.selected{
28-
box-shadow: 0 0 0 0.1em #66aaba73;
29-
30-
}
31-
.selected {
32-
background: #3f95a8cb !important;
33-
color: #fff !important;
34-
}
35-
.offmonth {
36-
color: rgb(216, 216, 216);
37-
}
38-
.offmonth.selected {
39-
background: rgba(55, 172, 151, 0.253);
40-
color: #ffffff;
41-
}
42-
.disabled,
43-
.disabled.selected {
44-
background-color: rgb(248 248 248) !important;
45-
}
46-
.weekend {
47-
color: #ffc482;
48-
}
49-
.weekend.offmonth,
50-
.weekend.disabled {
51-
color: #ffc582cb;
52-
}
1+
:root {
2+
--day-width: 1.5em;
3+
}
4+
.day {
5+
box-sizing: border-box;
6+
cursor: pointer;
7+
border-radius: calc(var(--border-radius) * 1.618);
8+
display: flex;
9+
justify-content: center;
10+
align-items: center;
11+
}
12+
.day:hover {
13+
background-color: rgba(0, 0, 0, 0.072);
14+
}
15+
.day > .value {
16+
color: rgb(36, 36, 36);
17+
width: 34px;
18+
height: 34px;
19+
line-height: 34px;
20+
}
21+
.today:not(.selected) {
22+
box-shadow: 0 0 0vw 0.1em var(--today-background);
23+
}
24+
.selected {
25+
background: var(--selected-background) !important;
26+
}
27+
.selected .value {
28+
font-weight: 700;
29+
color: var(--selected-color) !important;
30+
}
31+
.offmonth .value {
32+
color: var(--offmonth-color);
33+
}
34+
.offmonth.selected {
35+
background: var(--offmonth-background-color);
36+
}
37+
.disabled {
38+
background-color: var(--disabled--background-color) !important;
39+
pointer-events: none;
40+
}
41+
.disabled .value, .disabled.weekend .value{
42+
color: var(--disabled-color) !important;
43+
pointer-events: none;
44+
}
45+
.weekend .value {
46+
color: var(--weekend-color) !important;
47+
}
48+
.weekend.selected .value {
49+
color: var(--selected-color) !important;
50+
}
51+
.weekend.offmonth .value,
52+
.weekend.disabled .value {
53+
color: var(--weekend-color);
54+
}

src/day/day.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ type WeekProps = { day: Day, onClick: (e: React.MouseEvent<HTMLDivElement, Mouse
77
export default ({ day, onClick }: WeekProps) => {
88
return (
99
<div
10-
className={`day-container${day.disabled ? " disabled" : ""}${day.offmonth ? " offmonth" : ""}${day.weekend ? " weekend" : ""}${day.today ? " today" : ""}${day.selected ? " selected" : ""}`}
10+
className={`day${day.disabled ? " disabled" : ""}${day.offmonth ? " offmonth" : ""}${day.weekend ? " weekend" : ""}${day.today ? " today" : ""}${day.selected ? " selected" : ""}`}
1111
onClick={(e) => onClick(e, day.id)}
1212
>
13-
<span>{day.date}</span>
13+
<span className="value">{day.date}</span>
1414
</div>
1515
)
1616
}

0 commit comments

Comments
 (0)