Closed union-zakbutcher closed 2 months ago
I've poked around a bit an know this isn't exactly an easy thing to fix due to TS, but if there is a path forward, it would be VERY good to fix because ultimately all of the props flow down to the correct components / contexts, it's just a matter of playing nice with TS
If need-be, I can do a sym-link locally to test, but it's nearly 1am my time and I'm not feeling it right now. Lemme know if I need to do some more due diligence in my project before this is approved / merged
Hey @union-zakbutcher thanks for the detailed report! From a first look, your PR looks good to go. Give me some time to review it more carefully.
Not sure what you are trying to do there with the context providers. I am working on v9 which would actually simplify these parts (and the typings): if you are relying a lot to the DayPicker v8 internals, you may have hard time to refactor to v9.
Would you like to help us get v9 ready / or do you have time to help us testing it?
@gpbl I'm certainly open to the idea of helping develop / test v9 - I just can't make any firm commitments involving timeframes. If you have some general onboarding docs or something I can look at to get an idea of what help you need, I can take a look and get back to you on what I can actually help with!
As far as what I'm doing / needing, I was trying to resolve a type error in a storybook file where I'm documenting my custom implementation of react-day-picker
to match the design system I'm building out for my company and I needed to use the RootProvider
in those docs. The implementation is fairly large and private so sharing it here would be difficult, however I can try and summarize what I'm doing and we can go from there.
I've built two main components: Calendar
and DatePicker
. Calendar
is my main wrapper around react-day-picker
and handles low-level customizations like the theme color, some date formatting, our own custom context, and some other behavioral changes we need based on the UX we're targeting. Ultimately it boils down to a date-range picker and a single-date picker which use DayPicker
with the necessary props to make it behave as a date range picker or single date picker, respectively. This component is JUST the UI / UX of the actual calendar
The DatePicker
component is my higher-level, business-logic-included wrapper around Calendar
that includes UX smoothing and enhances the calendar with other components from our DS like a TextInput
for manually typing in a date and then updating Calendar
accordingly or making sure our onChange
callback is only called when a valid date has been entered so we don't erroneously call onChange
with a partial or invalid date.
I'm not actually using RootProvider
in my app, I'm just using it in my documentation in Storybook to force certain behaviors so I can "lock in" various permutations while using my components that depend on a context existing. I know all of the above is super vague so I've got a screenshot and the code from my documentation here to help out (note each const
is associated with a heading in the image, e.g. the Caption
element is the CalendarMonthNavigator
heading):
export const Caption = () => (
<StoryWrapper col>
<RootProvider>
<CalendarMonthNavigator displayMonth={DATE} />
</RootProvider>
</StoryWrapper>
);
export const Day = () => (
<StoryWrapper>
<Col className="w-fit items-stretch">
<Calendar>
<Row className="justify-between">
<Text.Body>Unselected Day</Text.Body>
<RootProvider>
<DayPickerProvider initialProps={{ mode: "single" }}>
<div className="w-fit">
<CalendarDay
date={subDays(DATE, 1)}
displayMonth={subDays(DATE, 1)}
/>
</div>
</DayPickerProvider>
</RootProvider>
</Row>
<Row className="justify-between">
<Text.Body>Selected Day</Text.Body>
<RootProvider selected={DATE}>
<DayPickerProvider initialProps={{ mode: "single" }}>
<div className="w-fit">
<CalendarDay date={DATE} displayMonth={DATE} />
</div>
</DayPickerProvider>
</RootProvider>
</Row>
<Row className="justify-between">
<Text.Body>Today (Unselected)</Text.Body>
<RootProvider>
<DayPickerProvider initialProps={{ mode: "single" }}>
<div className="w-fit">
<CalendarDay date={DATE} displayMonth={DATE} />
</div>
</DayPickerProvider>
</RootProvider>
</Row>
<Row className="justify-between">
<Text.Body>Date Range Start</Text.Body>
<RootRangeProvider mode="range" selected={DATE_RANGE}>
<div className="w-fit">
<CalendarDay
date={subDays(DATE, 2)}
displayMonth={subDays(DATE, 2)}
/>
</div>
</RootRangeProvider>
</Row>
<Row className="justify-between">
<Text.Body>Date Range Middle</Text.Body>
<RootRangeProvider mode="range" selected={DATE_RANGE}>
<div className="w-fit">
<CalendarDay
date={subDays(DATE, 1)}
displayMonth={subDays(DATE, 1)}
/>
</div>
</RootRangeProvider>
</Row>
<Row className="justify-between">
<Text.Body>Date Range End</Text.Body>
<RootRangeProvider mode="range" selected={DATE_RANGE}>
<div className="w-fit">
<CalendarDay date={DATE} displayMonth={DATE} />
</div>
</RootRangeProvider>
</Row>
</Calendar>
</Col>
</StoryWrapper>
);
export const SingleDatePicker = () => {
const [selected, setSelected] = useState<Date | undefined>(DATE);
return (
<StoryWrapper col>
<Calendar.Single selected={selected} onChange={setSelected} />
</StoryWrapper>
);
};
export const DateRangePicker = () => {
const [selected, setSelected] = useState<DateRange | undefined>(DATE_RANGE);
return (
<StoryWrapper col>
<Calendar.Range selected={selected} onChange={setSelected} />
</StoryWrapper>
);
};
export const CalendarTheming = () => {
const [selected, setSelected] = useState<DateRange | undefined>(DATE_RANGE);
return (
<StoryWrapper col>
<Text.ElementHeader>Blue Theme (Default)</Text.ElementHeader>
<Calendar>
<Calendar.Range selected={selected} onChange={setSelected} />
</Calendar>
<Text.ElementHeader>Green Theme</Text.ElementHeader>
<Calendar theme="green">
<Calendar.Range selected={selected} onChange={setSelected} />
</Calendar>
</StoryWrapper>
);
};
@gpbl Just wanted to ping you on my personal account because I was recently let go from my job and would rather any supporting efforts come from my own account. I'm still interested in helping out because this is a great library. If you have any type of roadmap or plan I can check out to orient myself with your goals for v9, I can check them out and figure out a way to start plugging in!
Hey @zakbutcher, thanks a lot for the follow ups - I'm facing some personal issues myself too, so please forgive my late reply.
I deeply appreciate your offer for help! I will go through your code and comments here in the upcoming days.
Description
I'm getting the following type error which makes sense b/c of type defs included in this project:
The provided type for
RootContext
is:Reproduced in this fork
If the above link doesn't work, it should be reproducible with this code:
Expected Behavior
I expect the
props
(orRootContext
) to accept all possible props, flagged as optional, for all included providers because all additional props are automatically spread into each provider via the following whereinitialProps
is passed to theinitialProps
prop of each providerProviders:
DayPickerProvider
SelectSingleProvider
SelectMultipleProvider
SelectRangeProvider
Actual Behavior
I get the following TS error:
Steps to Reproduce
See above setup (copied below) to use
RootProvider
as such:Possible Solution
Extend each interface accordingly, e.g.:
Screenshots
From Fork![image](https://github.com/gpbl/react-day-picker/assets/138704408/8d517f6f-6a18-44f0-a550-da6533f16bb5)
From VS Code