Skip to content

Commit

Permalink
feat: added "Months" custom component (#1917)
Browse files Browse the repository at this point in the history
Co-authored-by: gpbl <[email protected]>
  • Loading branch information
pawelgoc and gpbl authored Oct 13, 2023
1 parent f3327c9 commit 811732b
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 6 deletions.
27 changes: 27 additions & 0 deletions src/components/Months/Months.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { customRender } from 'test/render';

import { Months } from './Months';

let root: HTMLElement;

test('should use the default class name', () => {
const view = customRender(<Months>foo</Months>, {});
root = view.container.firstChild as HTMLElement;
expect(root).toHaveClass('rdp-months');
});

test('should use a custom class name', () => {
const view = customRender(<Months>foo</Months>, {
classNames: { months: 'foo' }
});
root = view.container.firstChild as HTMLElement;
expect(root).toHaveClass('foo');
});

test('should use a custom style', () => {
const view = customRender(<Months>foo</Months>, {
styles: { months: { color: 'red' } }
});
root = view.container.firstChild as HTMLElement;
expect(root).toHaveStyle({ color: 'red' });
});
19 changes: 19 additions & 0 deletions src/components/Months/Months.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PropsWithChildren } from 'react';

import { useDayPicker } from 'contexts/DayPicker';

/** The props for the {@link Months} component. */
export type MonthsProps = PropsWithChildren;

/**
* Render the wrapper for the mont grids.
*/
export function Months(props: MonthsProps): JSX.Element {
const { classNames, styles } = useDayPicker();

return (
<div className={classNames.months} style={styles.months}>
{props.children}
</div>
);
}
1 change: 1 addition & 0 deletions src/components/Months/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Months';
23 changes: 22 additions & 1 deletion src/components/Root/Root.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { RenderResult } from '@testing-library/react';
import { RenderResult, screen } from '@testing-library/react';
import { addDays } from 'date-fns';
import { DayPickerProps } from 'DayPicker';

import { customRender } from 'test/render';
import { getDayButton, queryMonthGrids } from 'test/selectors';
import { freezeBeforeAll } from 'test/utils';

import { MonthsProps } from 'components/Months';
import { defaultClassNames } from 'contexts/DayPicker/defaultClassNames';
import { ClassNames } from 'types/Styles';

Expand Down Expand Up @@ -54,6 +55,26 @@ describe('when using the "classNames" prop', () => {
});
});

describe('when using a custom "Months" component', () => {
function CustomMonths(props: MonthsProps) {
return (
<div>
<div data-testid="foo" />
{props.children}
</div>
);
}
beforeEach(() => {
render({ numberOfMonths: 3, components: { Months: CustomMonths } });
});
test('should render the custom component', () => {
expect(screen.getByTestId('foo')).toBeInTheDocument();
});
test('should still display the specified number of months', () => {
expect(queryMonthGrids()).toHaveLength(3);
});
});

describe('when using the "id" prop', () => {
const testId = 'foo';
beforeEach(() => render({ id: testId }));
Expand Down
10 changes: 5 additions & 5 deletions src/components/Root/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react';
import { DayPickerProps } from 'DayPicker';

import { Month } from 'components/Month';
import { Months } from 'components/Months';
import { useDayPicker } from 'contexts/DayPicker';
import { useFocusContext } from 'contexts/Focus';
import { useNavigation } from 'contexts/Navigation';
Expand Down Expand Up @@ -65,6 +66,8 @@ export function Root({ initialProps }: RootProps): JSX.Element {
};
}, {});

const MonthsComponent = initialProps.components?.Months ?? Months;

return (
<div
className={classNames.join(' ')}
Expand All @@ -76,14 +79,11 @@ export function Root({ initialProps }: RootProps): JSX.Element {
lang={initialProps.lang}
{...dataAttributes}
>
<div
className={dayPicker.classNames.months}
style={dayPicker.styles.months}
>
<MonthsComponent>
{navigation.displayMonths.map((month, i) => (
<Month key={i} displayIndex={i} displayMonth={month} />
))}
</div>
</MonthsComponent>
</div>
);
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export * from 'components/HeadRow';
export * from 'components/IconDropdown';
export * from 'components/IconRight';
export * from 'components/IconLeft';
export * from 'components/Months';
export * from 'components/Row';
export * from 'components/WeekNumber';

Expand Down
3 changes: 3 additions & 0 deletions src/types/DayPickerBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DayProps } from 'components/Day';
import { DayContentProps } from 'components/DayContent';
import { DropdownProps } from 'components/Dropdown';
import { FooterProps } from 'components/Footer';
import { MonthsProps } from 'components/Months';
import { RowProps } from 'components/Row';
import { WeekNumberProps } from 'components/WeekNumber';

Expand Down Expand Up @@ -417,6 +418,8 @@ export interface CustomComponents {
IconRight?: (props: StyledComponent) => JSX.Element | null;
/** The arrow left icon (used for the Navigation buttons). */
IconLeft?: (props: StyledComponent) => JSX.Element | null;
/** The component wrapping the month grids. */
Months?: (props: MonthsProps) => JSX.Element | null;
/** The component for the table rows. */
Row?: (props: RowProps) => JSX.Element | null;
/** The component for the week number in the table rows. */
Expand Down

0 comments on commit 811732b

Please sign in to comment.