Skip to content

Commit

Permalink
feat: support for nonce, lang, title global attributes (#1924)
Browse files Browse the repository at this point in the history
  • Loading branch information
gpbl committed Oct 7, 2023
1 parent 9d457c4 commit 7c8f0c9
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 19 deletions.
48 changes: 36 additions & 12 deletions src/components/Root/Root.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ freezeBeforeAll(today);
let container: HTMLElement;
let view: RenderResult;

function setup(dayPickerProps: DayPickerProps = {}) {
function render(dayPickerProps: DayPickerProps = {}) {
view = customRender(<Root initialProps={dayPickerProps} />, dayPickerProps);
container = view.container;
}

describe('when the number of months is 1', () => {
const props: DayPickerProps = { numberOfMonths: 1 };
beforeEach(() => {
setup(props);
render(props);
});
test('should display one month grid', () => {
expect(queryMonthGrids()).toHaveLength(1);
Expand All @@ -37,7 +37,7 @@ describe('when the number of months is 1', () => {
describe('when the number of months is greater than 1', () => {
const props: DayPickerProps = { numberOfMonths: 3 };
beforeEach(() => {
setup(props);
render(props);
});
test('should display the specified number of month grids', () => {
expect(queryMonthGrids()).toHaveLength(3);
Expand All @@ -49,25 +49,49 @@ describe('when using the "classNames" prop', () => {
root: 'foo'
};
beforeEach(() => {
setup({ classNames });
render({ classNames });
});
test('should display the specified number of month grids', () => {
test('should add the class to the container', () => {
expect(container.firstChild).toHaveClass('foo');
});
});

describe('when using the "id" prop', () => {
const testId = 'foo';
beforeEach(() => setup({ id: testId }));
test('should display the specified number of month grids', () => {
beforeEach(() => render({ id: testId }));
test('should add the "id" attribute', () => {
expect(container.firstChild).toHaveAttribute('id', testId);
});
});

describe('when using the "nonce" prop', () => {
const nonce = 'foo';
beforeEach(() => render({ nonce }));
test('should add the "nonce" attribute', () => {
expect(container.firstChild).toHaveAttribute('nonce', nonce);
});
});

describe('when using the "title" prop', () => {
const title = 'foo';
beforeEach(() => render({ title }));
test('should add the "title" attribute', () => {
expect(container.firstChild).toHaveAttribute('title', title);
});
});

describe('when using the "lang" prop', () => {
const lang = 'en-US';
beforeEach(() => render({ lang }));
test('should add the "lang" attribute', () => {
expect(container.firstChild).toHaveAttribute('lang', lang);
});
});

describe('when using the "className" prop', () => {
const props: DayPickerProps = { className: 'foo' };
beforeEach(() => {
setup(props);
render(props);
});
test('should append the class name to the root element', () => {
expect(container.firstChild).toHaveClass('rdp foo');
Expand All @@ -78,7 +102,7 @@ describe('when the "numberOfMonths" is greater than 1', () => {
const props: DayPickerProps = { numberOfMonths: 3 };
const expectedClassName = defaultClassNames.multiple_months;
beforeEach(() => {
setup(props);
render(props);
});
test(`should have the ${expectedClassName} class name`, () => {
expect(container.firstChild).toHaveClass(expectedClassName);
Expand All @@ -89,7 +113,7 @@ describe('when showing the week numbers', () => {
const props: DayPickerProps = { showWeekNumber: true };
const expectedClassName = defaultClassNames.with_weeknumber;
beforeEach(() => {
setup(props);
render(props);
});
test(`should have the ${expectedClassName} class name`, () => {
expect(container.firstChild).toHaveClass(expectedClassName);
Expand All @@ -103,7 +127,7 @@ describe('when "initialFocus" is set', () => {
};
describe('when a day is not selected', () => {
beforeEach(() => {
setup(baseProps);
render(baseProps);
});
test('should focus today', () => {
expect(getDayButton(today)).toHaveFocus();
Expand All @@ -121,7 +145,7 @@ describe('when "initialFocus" is set', () => {
const selected = addDays(today, 1);
const props: DayPickerProps = { ...baseProps, selected };
beforeEach(() => {
setup(props);
render(props);
});
test('should focus the selected day', () => {
expect(getDayButton(selected)).toHaveFocus();
Expand Down
3 changes: 3 additions & 0 deletions src/components/Root/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ export function Root({ initialProps }: RootProps): JSX.Element {
style={style}
dir={dayPicker.dir}
id={dayPicker.id}
nonce={initialProps.nonce}
title={initialProps.title}
lang={initialProps.lang}
{...dataAttributes}
>
<div
Expand Down
83 changes: 76 additions & 7 deletions src/types/DayPickerBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,35 +275,104 @@ export interface DayPickerBase {
*/
labels?: Partial<Labels>;

/**
* A map of formatters. Use the formatters to override the default formatting
* functions.
*/
formatters?: Partial<Formatters>;

/**
* The text direction of the calendar. Use `ltr` for left-to-right (default)
* or `rtl` for right-to-left.
*/
dir?: string;
dir?: HTMLDivElement['dir'];

/**
* A map of formatters. Use the formatters to override the default formatting
* functions.
* A cryptographic nonce ("number used once") which can be used by Content
* Security Policy for the inline `style` attributes.
**/
nonce?: HTMLDivElement['nonce'];

/**
* Add a `title` attribute to the container element.
**/
title?: HTMLDivElement['title'];

/**
* Add the language tag to the container element.
**/
lang?: HTMLDivElement['lang'];

/**
* Event callback fired when the next month button is clicked.
*/
formatters?: Partial<Formatters>;
onNextClick?: MonthChangeEventHandler;
/**
* Event callback fired when the previous month button is clicked.
*/
onPrevClick?: MonthChangeEventHandler;
/**
* Event callback fired when the week number is clicked. Requires
* `showWeekNumbers` set.
*/
onWeekNumberClick?: WeekNumberClickEventHandler;

/**
* Event callback fired when the user clicks on a day.
*/
onDayClick?: DayClickEventHandler;
/**
* Event callback fired when the user focuses on a day.
*/
onDayFocus?: DayFocusEventHandler;
/**
* Event callback fired when the user blurs from a day.
*/
onDayBlur?: DayFocusEventHandler;
/**
* Event callback fired when the user hovers on a day.
*/
onDayMouseEnter?: DayMouseEventHandler;
/**
* Event callback fired when the user hovers away from a day.
*/
onDayMouseLeave?: DayMouseEventHandler;
/**
* Event callback fired when the user presses a key on a day.
*/
onDayKeyDown?: DayKeyboardEventHandler;
/**
* Event callback fired when the user presses a key on a day.
*/
onDayKeyUp?: DayKeyboardEventHandler;
/**
* Event callback fired when the user presses a key on a day.
*/
onDayKeyPress?: DayKeyboardEventHandler;
/**
* Event callback fired when the pointer enters a day.
*/
onDayPointerEnter?: DayPointerEventHandler;
/**
* Event callback fired when the pointer leaves a day.
*/
onDayPointerLeave?: DayPointerEventHandler;
/**
* Event callback when a day touch event is canceled.
*/
onDayTouchCancel?: DayTouchEventHandler;
/**
* Event callback when a day touch event ends.
*/
onDayTouchEnd?: DayTouchEventHandler;
/**
* Event callback when a day touch event moves.
*/
onDayTouchMove?: DayTouchEventHandler;
/**
* Event callback when a day touch event starts.
*/
onDayTouchStart?: DayTouchEventHandler;
onNextClick?: MonthChangeEventHandler;
onPrevClick?: MonthChangeEventHandler;
onWeekNumberClick?: WeekNumberClickEventHandler;
}

/**
Expand Down

0 comments on commit 7c8f0c9

Please sign in to comment.