1- import { format as dfFormat , isValid as dfIsValid , parse as dfParse } from 'date-fns' ;
1+ import { format as dfFormat } from 'date-fns' ;
22import React from 'react' ;
33import styled from 'styled-components' ;
44
5- import { CalendarDate , fromDate , getLocalTimeZone , type DateValue } from '@internationalized/date' ;
5+ import { type DateValue } from '@internationalized/date' ;
66
77import type { Matcher , DateRange as RdpRange } from 'react-day-picker' ;
88import { DropdownSelectIcon , DropupSelectIcon } from '../../../icons' ;
@@ -13,11 +13,20 @@ import { Button } from '../Field/Button';
1313import type { FieldProps } from '../Field/Props' ;
1414import { FocusTrap , Popover } from '../Popover/Popover' ;
1515import { Chip , ChipRemoveButton , Chips } from './DatePicker.styled' ;
16+ import {
17+ calendarDateToDate ,
18+ dateToCalendarDate ,
19+ getSeparator ,
20+ inBounds ,
21+ multipleSummary ,
22+ stripTime ,
23+ toJSDate ,
24+ tryParse ,
25+ type Mode
26+ } from './util' ;
1627
1728type DateRange = RdpRange | undefined ;
1829
19- type Mode = 'single' | 'multiple' | 'range' ;
20-
2130type CommonProps = Pick < FieldProps , 'description' | 'errorMessage' > & {
2231 label ?: string ;
2332 placeholder ?: string ;
@@ -136,7 +145,10 @@ export function DatePicker(props: DatePickerProps): JSX.Element {
136145 const multipleValue = modeLocal === 'multiple' ? ( props as MultipleProps ) . value : undefined ;
137146 const rangeValue = modeLocal === 'range' ? ( props as RangeProps ) . value : undefined ;
138147
139- const sepForRange = React . useMemo < string > ( ( ) => getSeparator ( props ) , [ modeLocal , ( props as RangeProps ) . separator ] ) ;
148+ const sepForRange = React . useMemo < string > (
149+ ( ) => getSeparator ( modeLocal , ( props as RangeProps ) . separator ) ,
150+ [ modeLocal , ( props as RangeProps ) . separator ]
151+ ) ;
140152
141153 const neutralPlaceholder =
142154 placeholder ??
@@ -229,7 +241,7 @@ export function DatePicker(props: DatePickerProps): JSX.Element {
229241
230242 // input value
231243 const inputValue =
232- mode === 'multiple'
244+ modeLocal === 'multiple'
233245 ? multipleSummary (
234246 multipleValue ?? [ ] ,
235247 displayFormat ,
@@ -238,7 +250,7 @@ export function DatePicker(props: DatePickerProps): JSX.Element {
238250 )
239251 : text ;
240252
241- const readOnly = mode === 'multiple' || ! ! legacyIsDisabled ;
253+ const readOnly = modeLocal === 'multiple' || ! ! legacyIsDisabled ;
242254
243255 // calendar handlers
244256 const handleSelectSingle = React . useCallback (
@@ -493,58 +505,3 @@ export function DatePicker(props: DatePickerProps): JSX.Element {
493505 </ div >
494506 ) ;
495507}
496-
497- /* ---------- helpers ---------- */
498-
499- function tryParse ( raw : string , fmt : string , locale ?: Locale ) : Date | null {
500- if ( ! raw ?. trim ( ) ) return null ;
501- const p = dfParse ( raw , fmt , new Date ( ) , { locale } ) ;
502- if ( dfIsValid ( p ) ) return p ;
503- const loose = new Date ( raw ) ;
504- return dfIsValid ( loose ) ? loose : null ;
505- }
506-
507- function inBounds ( d : Date , min ?: Date , max ?: Date ) {
508- const t = stripTime ( d ) . getTime ( ) ;
509- return ( min ? t >= stripTime ( min ) . getTime ( ) : true ) && ( max ? t <= stripTime ( max ) . getTime ( ) : true ) ;
510- }
511-
512- function stripTime ( d : Date ) {
513- const x = new Date ( d ) ;
514- x . setHours ( 0 , 0 , 0 , 0 ) ;
515- return x ;
516- }
517-
518- function multipleSummary ( dates : Date [ ] , fmt : string , locale ?: Locale , strategy : 'firstDate' | 'count' = 'count' ) {
519- const count = dates . length ;
520- if ( count === 0 ) return '' ;
521- if ( strategy === 'firstDate' ) {
522- return dfFormat ( dates [ 0 ] , fmt , { locale } ) + ( count > 1 ? ` +${ count - 1 } ` : '' ) ;
523- }
524- return count === 1 ? dfFormat ( dates [ 0 ] , fmt , { locale } ) : `${ count } dates selected` ;
525- }
526-
527- function getSeparator ( props : DatePickerProps ) {
528- return ( props . mode === 'range' ? props . separator : undefined ) ?? ' – ' ;
529- }
530-
531- // eslint-disable-next-line @typescript-eslint/no-explicit-any
532- function toJSDate ( d : any ) : Date | undefined {
533- if ( ! d ) return undefined ;
534- if ( d instanceof Date ) return d ;
535- if ( typeof d === 'object' && 'year' in d && 'month' in d && 'day' in d ) {
536- return new Date ( d . year as number , ( d . month as number ) - 1 , d . day as number ) ;
537- }
538- return undefined ;
539- }
540-
541- function dateToCalendarDate ( d : Date ) : CalendarDate {
542- const zdt = fromDate ( d , getLocalTimeZone ( ) ) ;
543- return new CalendarDate ( zdt . year , zdt . month , zdt . day ) ;
544- }
545-
546- function calendarDateToDate ( dv : DateValue ) : Date {
547- // DateValue has year/month/day in Gregorian by default
548- // Construct a JS Date in local time at midnight.
549- return new Date ( dv . year , dv . month - 1 , dv . day ) ;
550- }
0 commit comments