Skip to content

Instantly share code, notes, and snippets.

@gmwill934
Created June 1, 2023 05:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gmwill934/b711980a2585faa4880f534793fba6a9 to your computer and use it in GitHub Desktop.
Save gmwill934/b711980a2585faa4880f534793fba6a9 to your computer and use it in GitHub Desktop.
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