Created
June 1, 2023 05:02
-
-
Save gmwill934/b711980a2585faa4880f534793fba6a9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createCalendar } from '@internationalized/date'; | |
import { useRef } from 'react'; | |
import { | |
DateValue, | |
useDatePicker, | |
AriaDatePickerProps, | |
useDateField, | |
useDateSegment, | |
} from 'react-aria'; | |
import { | |
DateFieldState, | |
DateSegment as TDateSegment, | |
useDateFieldState, | |
useDatePickerState, | |
} from 'react-stately'; | |
type DatepickerProps = { | |
label: string; | |
// eslint-disable-next-line @typescript-eslint/no-explicit-any | |
onChange: (...event: any) => void; | |
value: DateValue; | |
}; | |
type DateFieldProps = AriaDatePickerProps<DateValue>; | |
type DateSegmentProps = { | |
segment: TDateSegment; | |
state: DateFieldState; | |
}; | |
export function Datepicker({ | |
label, | |
onChange, | |
value, | |
...props | |
}: DatepickerProps) { | |
const state = useDatePickerState({ | |
label, | |
onChange, | |
value, | |
...props, | |
}); | |
const ref = useRef<HTMLDivElement>(null); | |
const { labelProps, fieldProps, groupProps } = useDatePicker( | |
{ label, onChange, value }, | |
state, | |
ref | |
); | |
return ( | |
<div className='flex flex-col gap-px shadow p-2 border'> | |
{/* Label for the Datepicker */} | |
<label className='text-xs' {...labelProps}> | |
{label} | |
</label> | |
{/* This div will act as a grouping element */} | |
<div ref={ref} {...groupProps}> | |
{/* This div will act as the input element */} | |
<DateField {...fieldProps} /> | |
</div> | |
</div> | |
); | |
} | |
function DateField(props: DateFieldProps) { | |
const state = useDateFieldState({ | |
...props, | |
// why is this? | |
locale: 'es', | |
createCalendar, | |
}); | |
const ref = useRef<HTMLDivElement>(null); | |
const { fieldProps } = useDateField(props, state, ref); | |
return ( | |
<div {...fieldProps} ref={ref} className='flex'> | |
{state.segments.map((segment, i) => ( | |
<DateSegment key={i} state={state} segment={segment} /> | |
))} | |
</div> | |
); | |
} | |
function DateSegment({ segment, state }: DateSegmentProps) { | |
const ref = useRef<HTMLDivElement>(null); | |
const { segmentProps } = useDateSegment(segment, state, ref); | |
return ( | |
<div | |
ref={ref} | |
style={{ | |
...segmentProps.style, | |
minWidth: | |
segment.maxValue != null | |
? String(segment.maxValue).length + 'ch' | |
: '', | |
}} | |
{...segmentProps} | |
className='px-0.5 box-content tabular-nums text-right outline-none focus:bg-blue-600 rounded-md focus:text-white group' | |
> | |
<span | |
aria-hidden='true' | |
className='block w-full text-center italic text-gray-500 group-focus:text-white' | |
style={{ | |
visibility: segment.isPlaceholder ? 'inherit' : 'hidden', | |
height: segment.isPlaceholder ? '' : 0, | |
pointerEvents: 'none', | |
}} | |
> | |
{segment.placeholder} | |
</span> | |
{segment.isPlaceholder ? '' : segment.text} | |
</div> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment