main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
import { DayPickerProps } from 'DayPicker';
import { customRender } from 'test/render';
import { getNextButton, getPrevButton } from 'test/selectors';
import { user } from 'test/user';
import { Navigation, NavigationProps } from './Navigation';
let root: HTMLElement;
function setup(props: NavigationProps, dayPickerProps?: DayPickerProps) {
const view = customRender(<Navigation {...props} />, dayPickerProps);
root = view.container.firstChild as HTMLElement;
}
const props: NavigationProps = {
previousMonth: new Date(2021, 3),
nextMonth: new Date(2021, 5),
displayMonth: new Date(2021, 4),
hidePrevious: false,
hideNext: false,
onNextClick: jest.fn(),
onPreviousClick: jest.fn()
};
const dayPickerProps = {
classNames: {
nav: 'foo'
},
styles: {
nav: { color: 'red' }
},
components: {
IconRight: () => <svg>IconRight</svg>,
IconLeft: () => <svg>IconLeft</svg>
}
};
describe('when rendered', () => {
beforeEach(() => {
setup(props, dayPickerProps);
});
test('should add the class name', () => {
expect(root).toHaveClass(dayPickerProps.classNames.nav);
});
test('should apply the style', () => {
expect(root).toHaveStyle(dayPickerProps.styles.nav);
});
test('the previous button should display the left icon', () => {
const icons = root.getElementsByTagName('svg');
expect(icons[0]).toHaveTextContent('IconLeft');
});
test('the next button should display the right icon', () => {
const icons = root.getElementsByTagName('svg');
expect(icons[1]).toHaveTextContent('IconRight');
});
test('the previous button should be named "previous-month"', () => {
expect(getPrevButton()).toHaveAttribute('name', 'previous-month');
});
test('the next button should be named "next-month"', () => {
expect(getNextButton()).toHaveAttribute('name', 'next-month');
});
beforeEach(async () => {
await user.click(getPrevButton());
});
test('should call "onPreviousClick"', () => {
expect(props.onPreviousClick).toHaveBeenCalled();
});
describe('when clicking the next button', () => {
beforeEach(async () => {
await user.click(getNextButton());
});
test('should call "onNextClick"', () => {
expect(props.onNextClick).toHaveBeenCalled();
});
});
});
describe('when in right-to-left direction', () => {
beforeEach(() => {
setup(props, { ...dayPickerProps, dir: 'rtl' });
});
test('the previous button should display the right icon', () => {
const icons = root.getElementsByTagName('svg');
expect(icons[0]).toHaveTextContent('IconRight');
});
test('the next button should display the left icon', () => {
const icons = root.getElementsByTagName('svg');
expect(icons[1]).toHaveTextContent('IconLeft');
});
describe('when clicking the previous button', () => {
beforeEach(async () => {
await user.click(getPrevButton());
});
test('should call "onPreviousClick"', () => {
expect(props.onPreviousClick).toHaveBeenCalled();
});
});
describe('when clicking the next button', () => {
beforeEach(async () => {
await user.click(getNextButton());
});
test('should call "onNextClick"', () => {
expect(props.onNextClick).toHaveBeenCalled();
});
});
});
describe('when the previous month is undefined', () => {
beforeEach(() => {
setup({ ...props, previousMonth: undefined }, dayPickerProps);
});
test('the previous button should be disabled', () => {
expect(getPrevButton()).toBeDisabled();
});
test('the next button should be enabled', () => {
expect(getNextButton()).toBeEnabled();
});
});
describe('when the next month is undefined', () => {
beforeEach(() => {
setup({ ...props, nextMonth: undefined }, dayPickerProps);
});
test('the previous button should be enabled', () => {
expect(getPrevButton()).toBeEnabled();
});
test('the next button should be disabled', () => {
expect(getNextButton()).toBeDisabled();
});
});

View File

@@ -0,0 +1,104 @@
import { MouseEventHandler } from 'react';
import { IconLeft } from 'components/IconLeft';
import { IconRight } from 'components/IconRight';
import { useDayPicker } from 'contexts/DayPicker';
import { Button } from '../Button';
/** The props for the {@link Navigation} component. */
export interface NavigationProps {
/** The month where the caption is displayed. */
displayMonth: Date;
/** The previous month. */
previousMonth?: Date;
/** The next month. */
nextMonth?: Date;
/** Hide the previous button. */
hidePrevious: boolean;
/** Hide the next button. */
hideNext: boolean;
/** Event handler when the next button is clicked. */
onNextClick: MouseEventHandler<HTMLButtonElement>;
/** Event handler when the previous button is clicked. */
onPreviousClick: MouseEventHandler<HTMLButtonElement>;
}
/** A component rendering the navigation buttons or the drop-downs. */
export function Navigation(props: NavigationProps): JSX.Element {
const {
dir,
locale,
classNames,
styles,
labels: { labelPrevious, labelNext },
components
} = useDayPicker();
if (!props.nextMonth && !props.previousMonth) {
return <></>;
}
const previousLabel = labelPrevious(props.previousMonth, { locale });
const previousClassName = [
classNames.nav_button,
classNames.nav_button_previous
].join(' ');
const nextLabel = labelNext(props.nextMonth, { locale });
const nextClassName = [
classNames.nav_button,
classNames.nav_button_next
].join(' ');
const IconRightComponent = components?.IconRight ?? IconRight;
const IconLeftComponent = components?.IconLeft ?? IconLeft;
return (
<div className={classNames.nav} style={styles.nav}>
{!props.hidePrevious && (
<Button
name="previous-month"
aria-label={previousLabel}
className={previousClassName}
style={styles.nav_button_previous}
disabled={!props.previousMonth}
onClick={props.onPreviousClick}
>
{dir === 'rtl' ? (
<IconRightComponent
className={classNames.nav_icon}
style={styles.nav_icon}
/>
) : (
<IconLeftComponent
className={classNames.nav_icon}
style={styles.nav_icon}
/>
)}
</Button>
)}
{!props.hideNext && (
<Button
name="next-month"
aria-label={nextLabel}
className={nextClassName}
style={styles.nav_button_next}
disabled={!props.nextMonth}
onClick={props.onNextClick}
>
{dir === 'rtl' ? (
<IconLeftComponent
className={classNames.nav_icon}
style={styles.nav_icon}
/>
) : (
<IconRightComponent
className={classNames.nav_icon}
style={styles.nav_icon}
/>
)}
</Button>
)}
</div>
);
}

View File

@@ -0,0 +1 @@
export * from './Navigation';