diff --git a/packages/fluentui/CHANGELOG.md b/packages/fluentui/CHANGELOG.md
index 1eb7881cf83358..dd07189e7c946f 100644
--- a/packages/fluentui/CHANGELOG.md
+++ b/packages/fluentui/CHANGELOG.md
@@ -18,6 +18,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [Unreleased]
+### Fixes
+- `Datepicker`: add onCalendarOpenStateChange prop. @jurokapsiar ([#28136](https://github.com/microsoft/fluentui/pull/28136))
+
## [v0.66.4](https://github.com/microsoft/fluentui/tree/@fluentui/react-northstar_v0.66.4) (2023-03-10)
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-northstar_v0.66.3..@fluentui/react-northstar_v0.66.4)
diff --git a/packages/fluentui/docs/src/examples/components/Datepicker/Types/DatepickerExampleOpen.shorthand.tsx b/packages/fluentui/docs/src/examples/components/Datepicker/Types/DatepickerExampleOpen.shorthand.tsx
index cf9926bb91c882..1ee55b7d13f917 100644
--- a/packages/fluentui/docs/src/examples/components/Datepicker/Types/DatepickerExampleOpen.shorthand.tsx
+++ b/packages/fluentui/docs/src/examples/components/Datepicker/Types/DatepickerExampleOpen.shorthand.tsx
@@ -3,9 +3,13 @@ import * as React from 'react';
import { Datepicker } from '@fluentui/react-northstar';
const DatepickerExampleOpen = () => {
- const [open] = useBooleanKnob({ name: 'open' });
-
- return ;
+ const [open, setOpen] = useBooleanKnob({ name: 'open' });
+ return (
+ setOpen(calendarOpenState)}
+ />
+ );
};
export default DatepickerExampleOpen;
diff --git a/packages/fluentui/react-northstar/src/components/Datepicker/Datepicker.tsx b/packages/fluentui/react-northstar/src/components/Datepicker/Datepicker.tsx
index 9f2fc59d0dcb49..42540f07835676 100644
--- a/packages/fluentui/react-northstar/src/components/Datepicker/Datepicker.tsx
+++ b/packages/fluentui/react-northstar/src/components/Datepicker/Datepicker.tsx
@@ -100,6 +100,14 @@ export interface DatepickerProps extends UIComponentProps, Partial;
+
/** Initial 'selectedDate' value. */
defaultSelectedDate?: Date;
@@ -253,6 +261,21 @@ export const Datepicker = React.forwardRef((pro
: '',
);
+ const trySetOpenState = (
+ newValue: boolean,
+ event:
+ | React.SyntheticEvent
+ | React.KeyboardEvent
+ | React.MouseEvent
+ | KeyboardEvent
+ | MouseEvent
+ | TouchEvent
+ | WheelEvent,
+ ) => {
+ setOpenState(newValue);
+ _.invoke(props, 'onCalendarOpenStateChange', event, { ...props, ...{ calendarOpenState: newValue } });
+ };
+
const calendarOptions: IDayGridOptions = {
selectedDate,
navigatedDate: !!selectedDate && !error ? selectedDate : props.today ?? new Date(),
@@ -274,10 +297,10 @@ export const Datepicker = React.forwardRef((pro
actionHandlers: {
open: e => {
if (allowManualInput) {
- setOpenState(!openState);
+ trySetOpenState(!openState, e);
} else {
// Keep popup open in case we can only enter the date through calendar.
- setOpenState(true);
+ trySetOpenState(true, e);
}
e.preventDefault();
@@ -309,7 +332,7 @@ export const Datepicker = React.forwardRef((pro
onDateChange: (e, itemProps) => {
const targetDay = itemProps.value;
setSelectedDate(targetDay.originalDate);
- setOpenState(false);
+ trySetOpenState(false, e);
setError('');
setFormattedDate(valueFormatter(targetDay.originalDate));
@@ -325,10 +348,10 @@ export const Datepicker = React.forwardRef((pro
const overrideInputProps = (predefinedProps: InputProps): InputProps => ({
onClick: (e): void => {
if (allowManualInput) {
- setOpenState(!openState);
+ trySetOpenState(!openState, e);
} else {
// Keep popup open in case we can only enter the date through calendar.
- setOpenState(true);
+ trySetOpenState(true, e);
}
_.invoke(predefinedProps, 'onClick', e, predefinedProps);
@@ -415,7 +438,7 @@ export const Datepicker = React.forwardRef((pro
onOpenChange: (e, { open }) => {
// In case the event is a click on input, we ignore such events as it should be directly handled by input.
if (!(e.type === 'click' && e.target === inputRef?.current)) {
- setOpenState(open);
+ trySetOpenState(open, e);
_.invoke(predefinedProps, 'onOpenChange', e, { open });
}
},
@@ -454,6 +477,7 @@ Datepicker.propTypes = {
fallbackToLastCorrectDateOnBlur: PropTypes.bool,
defaultCalendarOpenState: PropTypes.bool,
calendarOpenState: PropTypes.bool,
+ onCalendarOpenStateChange: PropTypes.func,
selectedDate: PropTypes.instanceOf(Date),
defaultSelectedDate: PropTypes.instanceOf(Date),