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,72 @@
import { fireEvent, screen } from '@testing-library/react';
import { DayPickerProps } from 'DayPicker';
import { customRender } from 'test/render';
import { freezeBeforeAll } from 'test/utils';
import { Dropdown, DropdownProps } from 'components/Dropdown';
import { defaultClassNames } from 'contexts/DayPicker/defaultClassNames';
import { CustomComponents } from 'types/DayPickerBase';
const today = new Date(2021, 8);
freezeBeforeAll(today);
function setup(props: DropdownProps, dayPickerProps?: DayPickerProps) {
customRender(<Dropdown {...props} />, dayPickerProps);
}
const props: Required<DropdownProps> = {
name: 'dropdown',
'aria-label': 'foo',
onChange: jest.fn(),
caption: 'Some caption',
className: 'test',
value: 'bar',
children: <option value={'bar'} />,
style: {}
};
describe('when rendered', () => {
let combobox: HTMLElement;
let label: HTMLElement;
beforeEach(() => {
setup(props);
combobox = screen.getByRole('combobox');
label = screen.getByText(props['aria-label']);
});
test('should render the vhidden aria label', () => {
expect(label).toHaveClass(defaultClassNames.vhidden);
});
test('should render the combobox', () => {
expect(combobox).toBeInTheDocument();
});
describe('when the combobox changes', () => {
beforeEach(() => {
fireEvent.change(combobox);
});
test('should call the "onChange" eve, nt handler', () => {
expect(props.onChange).toHaveBeenCalled();
});
});
test('should render the combobox with the given value', () => {
expect(combobox).toHaveValue(props.value);
});
});
describe('when using a custom IconDropdown component', () => {
const components: CustomComponents = {
IconDropdown: () => <div>Custom IconDropdown</div>
};
beforeEach(() => {
setup(props, { components });
});
test('it should render the custom component instead', () => {
expect(screen.getByText('Custom IconDropdown')).toBeInTheDocument();
});
});

View File

@@ -0,0 +1,66 @@
import {
ChangeEventHandler,
CSSProperties,
ReactNode,
SelectHTMLAttributes
} from 'react';
import { IconDropdown } from 'components/IconDropdown';
import { useDayPicker } from 'contexts/DayPicker';
/** The props for the {@link Dropdown} component. */
export interface DropdownProps {
/** The name attribute of the element. */
name?: string;
/** The caption displayed to replace the hidden select. */
caption?: ReactNode;
children?: SelectHTMLAttributes<HTMLSelectElement>['children'];
className?: string;
['aria-label']?: string;
style?: CSSProperties;
/** The selected value. */
value?: string | number;
onChange?: ChangeEventHandler<HTMLSelectElement>;
}
/**
* Render a styled select component displaying a caption and a custom
* drop-down icon.
*/
export function Dropdown(props: DropdownProps): JSX.Element {
const { onChange, value, children, caption, className, style } = props;
const dayPicker = useDayPicker();
const IconDropdownComponent =
dayPicker.components?.IconDropdown ?? IconDropdown;
return (
<div className={className} style={style}>
<span className={dayPicker.classNames.vhidden}>
{props['aria-label']}
</span>
<select
name={props.name}
aria-label={props['aria-label']}
className={dayPicker.classNames.dropdown}
style={dayPicker.styles.dropdown}
value={value}
onChange={onChange}
>
{children}
</select>
<div
className={dayPicker.classNames.caption_label}
style={dayPicker.styles.caption_label}
aria-hidden="true"
>
{caption}
{
<IconDropdownComponent
className={dayPicker.classNames.dropdown_icon}
style={dayPicker.styles.dropdown_icon}
/>
}
</div>
</div>
);
}

View File

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