@@ -2,133 +2,83 @@ import React, { ReactElement } from 'react';
22import {
33 Calendar as BaseCalendar ,
44 CalendarProps as BaseCalendarProps ,
5- CalendarCell ,
6- CalendarGrid as BaseCalendarGrid ,
5+ RangeCalendarProps ,
76 CalendarGridHeader ,
87 CalendarGridBody ,
9- CalendarHeaderCell ,
10- Heading as BaseHeading ,
118 DateValue ,
12- Button as BaseButton
9+ RangeCalendar
1310} from 'react-aria-components' ;
14- import styled from 'styled-components' ;
1511import ChevronLeftIcon from '../../../icons/arrows/ChevronLeftIcon' ;
1612import ChevronRightIcon from '../../../icons/arrows/ChevronRightIcon' ;
17- import { getSemanticValue } from '../../../essentials/experimental' ;
18- import { textStyles } from '../Text/Text' ;
19- import { get } from '../../../utils/experimental/themeGet' ;
2013
21- const Header = styled . header `
22- display: flex;
23- align-items: center;
24- justify-content: space-between;
25- padding-bottom: ${ get ( 'space.3' ) } ;
26- ` ;
27-
28- const Button = styled ( BaseButton ) `
29- appearance: none;
30- background: none;
31- border: none;
32- display: flex;
33- cursor: pointer;
34- margin: 0;
35- padding: 0;
36- color: ${ getSemanticValue ( 'on-surface' ) } ;
37- outline: 0;
38-
39- &[data-focused] {
40- outline: ${ getSemanticValue ( 'interactive' ) } solid 0.125rem;
41- border-radius: ${ get ( 'radii.2' ) } ;
42- }
43-
44- &[data-disabled] {
45- opacity: 0;
46- }
47- ` ;
48-
49- const Heading = styled ( BaseHeading ) `
50- margin: 0;
51- color: ${ getSemanticValue ( 'on-surface' ) } ;
52- ${ textStyles . variants . title2 }
53- ` ;
54-
55- const CalendarGrid = styled ( BaseCalendarGrid ) `
56- border-collapse: collapse;
57- border-spacing: 0;
58-
59- td {
60- padding: 0;
61- }
62-
63- th {
64- padding: 0 0 ${ get ( 'space.1' ) } ;
65- }
66- ` ;
67-
68- const WeekDay = styled ( CalendarHeaderCell ) `
69- color: ${ getSemanticValue ( 'on-surface' ) } ;
70- ${ textStyles . variants . label2 }
71- ` ;
72-
73- const Day = styled ( CalendarCell ) `
74- display: flex;
75- align-items: center;
76- justify-content: center;
77- color: ${ getSemanticValue ( 'on-surface' ) } ;
78- width: 2.5rem;
79- height: 2.5rem;
80- border-radius: 50%;
81- ${ textStyles . variants . label2 }
82- transition: background ease 200ms;
83-
84- &[data-focused] {
85- outline: ${ getSemanticValue ( 'interactive' ) } solid 0.125rem;
86- }
87-
88- &[data-hovered] {
89- cursor: pointer;
90- background: ${ getSemanticValue ( 'surface-variant' ) } ;
91- }
92-
93- &[data-selected] {
94- background: ${ getSemanticValue ( 'interactive-container' ) } ;
95- color: ${ getSemanticValue ( 'on-interactive-container' ) } ;
96- }
97-
98- &[data-disabled] {
99- opacity: 0.38;
100- }
14+ import * as Styled from './Calendar.styled' ;
15+
16+ type CalendarProps = { visibleMonths ?: 1 | 2 | 3 } & (
17+ | ( { selectionType ?: 'single' } & Omit < BaseCalendarProps < DateValue > , 'visibleDuration' > )
18+ | ( { selectionType : 'range' } & Omit < RangeCalendarProps < DateValue > , 'visibleDuration' > )
19+ ) ;
20+
21+ function Calendar ( {
22+ value,
23+ minValue,
24+ defaultValue,
25+ maxValue,
26+ onChange,
27+ selectionType = 'single' ,
28+ visibleMonths = 1 ,
29+ ...props
30+ } : CalendarProps ) : ReactElement {
31+ const calendarInner = (
32+ < >
33+ < Styled . Header >
34+ < Styled . Button slot = "previous" >
35+ < ChevronLeftIcon size = { 24 } />
36+ </ Styled . Button >
37+ < Styled . Heading />
38+ < Styled . Button slot = "next" >
39+ < ChevronRightIcon size = { 24 } />
40+ </ Styled . Button >
41+ </ Styled . Header >
42+ < Styled . MonthGrid >
43+ { Array . from ( { length : visibleMonths } ) . map ( ( _ , index ) => (
44+ // eslint-disable-next-line react/no-array-index-key
45+ < Styled . CalendarGrid weekdayStyle = "short" key = { `month_${ index } ` } offset = { { months : index } } >
46+ < CalendarGridHeader > { weekDay => < Styled . WeekDay > { weekDay } </ Styled . WeekDay > } </ CalendarGridHeader >
47+ < CalendarGridBody >
48+ { date => (
49+ < Styled . Day date = { date } >
50+ { ( { formattedDate } ) =>
51+ formattedDate . length > 1 ? formattedDate : `0${ formattedDate } `
52+ }
53+ </ Styled . Day >
54+ ) }
55+ </ CalendarGridBody >
56+ </ Styled . CalendarGrid >
57+ ) ) }
58+ </ Styled . MonthGrid >
59+ </ >
60+ ) ;
10161
102- &[data-outside-month] {
103- opacity: 0;
62+ if ( selectionType === 'single' ) {
63+ return (
64+ < BaseCalendar
65+ { ...( props as BaseCalendarProps < DateValue > ) }
66+ visibleDuration = { { months : visibleMonths } }
67+ data-selection-type = "single"
68+ >
69+ { calendarInner }
70+ </ BaseCalendar >
71+ ) ;
10472 }
105- ` ;
10673
107- type CalendarProps = BaseCalendarProps < DateValue > ;
108-
109- function Calendar ( { value, minValue, defaultValue, maxValue, onChange, ...props } : CalendarProps ) : ReactElement {
11074 return (
111- < BaseCalendar { ...props } >
112- < Header >
113- < Button slot = "previous" >
114- < ChevronLeftIcon size = { 24 } />
115- </ Button >
116- < Heading />
117- < Button slot = "next" >
118- < ChevronRightIcon size = { 24 } />
119- </ Button >
120- </ Header >
121- < CalendarGrid weekdayStyle = "short" >
122- < CalendarGridHeader > { weekDay => < WeekDay > { weekDay } </ WeekDay > } </ CalendarGridHeader >
123- < CalendarGridBody >
124- { date => (
125- < Day date = { date } >
126- { ( { formattedDate } ) => ( formattedDate . length > 1 ? formattedDate : `0${ formattedDate } ` ) }
127- </ Day >
128- ) }
129- </ CalendarGridBody >
130- </ CalendarGrid >
131- </ BaseCalendar >
75+ < RangeCalendar
76+ { ...( props as RangeCalendarProps < DateValue > ) }
77+ visibleDuration = { { months : visibleMonths } }
78+ data-selection-type = "range"
79+ >
80+ { calendarInner }
81+ </ RangeCalendar >
13282 ) ;
13383}
13484
0 commit comments