@jobber/components 6.105.1 → 6.105.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,6 +40,10 @@ interface BaseDatePickerProps {
40
40
  * Change handler when the selected month changes
41
41
  */
42
42
  onMonthChange?(val: Date): void;
43
+ /**
44
+ * Callback when the calendar open state changes
45
+ */
46
+ onOpenChange?(open: boolean): void;
43
47
  }
44
48
  interface DatePickerModalProps extends BaseDatePickerProps {
45
49
  /**
@@ -66,5 +70,5 @@ interface DatePickerInlineProps extends BaseDatePickerProps {
66
70
  readonly inline?: boolean;
67
71
  }
68
72
  type DatePickerProps = XOR<DatePickerModalProps, DatePickerInlineProps>;
69
- export declare function DatePicker({ onChange, onMonthChange, activator, inline, selected, readonly, disabled, fullWidth, smartAutofocus, maxDate, minDate, highlightDates, firstDayOfWeek, }: DatePickerProps): React.JSX.Element;
73
+ export declare function DatePicker({ onChange, onMonthChange, onOpenChange, activator, inline, selected, readonly, disabled, fullWidth, smartAutofocus, maxDate, minDate, highlightDates, firstDayOfWeek, }: DatePickerProps): React.JSX.Element;
70
74
  export {};
@@ -12705,7 +12705,7 @@ function useFocusOnSelectedDate() {
12705
12705
  }
12706
12706
 
12707
12707
  /*eslint max-statements: ["error", 14]*/
12708
- function DatePicker({ onChange, onMonthChange, activator, inline, selected, readonly = false, disabled = false, fullWidth = false, smartAutofocus = true, maxDate, minDate, highlightDates, firstDayOfWeek, }) {
12708
+ function DatePicker({ onChange, onMonthChange, onOpenChange, activator, inline, selected, readonly = false, disabled = false, fullWidth = false, smartAutofocus = true, maxDate, minDate, highlightDates, firstDayOfWeek, }) {
12709
12709
  const { ref, focusOnSelectedDate } = useFocusOnSelectedDate();
12710
12710
  const [open, setOpen] = React.useState(false);
12711
12711
  const { dateFormat, firstDayOfWeek: contextFirstDayOfWeek } = AtlantisContext.useAtlantisContext();
@@ -12752,9 +12752,11 @@ function DatePicker({ onChange, onMonthChange, activator, inline, selected, read
12752
12752
  }
12753
12753
  function handleCalendarOpen() {
12754
12754
  setOpen(true);
12755
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(true);
12755
12756
  }
12756
12757
  function handleCalendarClose() {
12757
12758
  setOpen(false);
12759
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(false);
12758
12760
  }
12759
12761
  }
12760
12762
  function useEscapeKeyToCloseDatePicker(open, ref) {
@@ -12703,7 +12703,7 @@ function useFocusOnSelectedDate() {
12703
12703
  }
12704
12704
 
12705
12705
  /*eslint max-statements: ["error", 14]*/
12706
- function DatePicker({ onChange, onMonthChange, activator, inline, selected, readonly = false, disabled = false, fullWidth = false, smartAutofocus = true, maxDate, minDate, highlightDates, firstDayOfWeek, }) {
12706
+ function DatePicker({ onChange, onMonthChange, onOpenChange, activator, inline, selected, readonly = false, disabled = false, fullWidth = false, smartAutofocus = true, maxDate, minDate, highlightDates, firstDayOfWeek, }) {
12707
12707
  const { ref, focusOnSelectedDate } = useFocusOnSelectedDate();
12708
12708
  const [open, setOpen] = useState(false);
12709
12709
  const { dateFormat, firstDayOfWeek: contextFirstDayOfWeek } = useAtlantisContext();
@@ -12750,9 +12750,11 @@ function DatePicker({ onChange, onMonthChange, activator, inline, selected, read
12750
12750
  }
12751
12751
  function handleCalendarOpen() {
12752
12752
  setOpen(true);
12753
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(true);
12753
12754
  }
12754
12755
  function handleCalendarClose() {
12755
12756
  setOpen(false);
12757
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(false);
12756
12758
  }
12757
12759
  }
12758
12760
  function useEscapeKeyToCloseDatePicker(open, ref) {
@@ -103,21 +103,47 @@ function useInputDateActivatorActions({ onChange, onBlur, onFocus, }) {
103
103
 
104
104
  const InputDateRebuilt = React.forwardRef((props, forwardedRef) => {
105
105
  const { onChange } = props;
106
+ const isCalendarOpenRef = React.useRef(false);
107
+ const inputFocusedRef = React.useRef(false);
108
+ const compositeFocusedRef = React.useRef(false);
109
+ const lastBlurEventRef = React.useRef(null);
106
110
  return (React.createElement(DatePicker.DatePicker, { selected: props.value, onChange: newValue => {
107
111
  onChange(newValue);
108
- }, disabled: props.disabled, readonly: props.readOnly, fullWidth: !props.inline, minDate: props.minDate, maxDate: props.maxDate, smartAutofocus: false, activator: InputDateActivator }));
112
+ }, disabled: props.disabled, readonly: props.readOnly, fullWidth: !props.inline, minDate: props.minDate, maxDate: props.maxDate, smartAutofocus: false, activator: InputDateActivator, onOpenChange: open => {
113
+ var _a;
114
+ isCalendarOpenRef.current = open;
115
+ // When calendar closes, fire onBlur if input is also not focused
116
+ if (!open &&
117
+ !inputFocusedRef.current &&
118
+ compositeFocusedRef.current &&
119
+ lastBlurEventRef.current) {
120
+ compositeFocusedRef.current = false;
121
+ (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, lastBlurEventRef.current);
122
+ }
123
+ } }));
109
124
  function InputDateActivator(activatorProps) {
110
125
  const { onClick, value } = activatorProps;
111
126
  const { handleChange, handleFocus, handleBlur, isFocused } = useInputDateActivatorActions({
112
127
  onChange: activatorProps.onChange,
113
128
  onFocus: event => {
114
129
  var _a, _b;
115
- (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, event);
130
+ inputFocusedRef.current = true;
131
+ // Fire parent's onFocus only when the composite component first receives focus
132
+ if (!compositeFocusedRef.current) {
133
+ compositeFocusedRef.current = true;
134
+ (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, event);
135
+ }
116
136
  (_b = activatorProps.onFocus) === null || _b === void 0 ? void 0 : _b.call(activatorProps);
117
137
  },
118
138
  onBlur: event => {
119
139
  var _a, _b;
120
- (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, event);
140
+ inputFocusedRef.current = false;
141
+ lastBlurEventRef.current = event;
142
+ // Only fire parent's onBlur if calendar is also closed
143
+ if (!isCalendarOpenRef.current && compositeFocusedRef.current) {
144
+ compositeFocusedRef.current = false;
145
+ (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, event);
146
+ }
121
147
  (_b = activatorProps.onBlur) === null || _b === void 0 ? void 0 : _b.call(activatorProps);
122
148
  },
123
149
  });
@@ -101,21 +101,47 @@ function useInputDateActivatorActions({ onChange, onBlur, onFocus, }) {
101
101
 
102
102
  const InputDateRebuilt = forwardRef((props, forwardedRef) => {
103
103
  const { onChange } = props;
104
+ const isCalendarOpenRef = useRef(false);
105
+ const inputFocusedRef = useRef(false);
106
+ const compositeFocusedRef = useRef(false);
107
+ const lastBlurEventRef = useRef(null);
104
108
  return (React__default.createElement(DatePicker, { selected: props.value, onChange: newValue => {
105
109
  onChange(newValue);
106
- }, disabled: props.disabled, readonly: props.readOnly, fullWidth: !props.inline, minDate: props.minDate, maxDate: props.maxDate, smartAutofocus: false, activator: InputDateActivator }));
110
+ }, disabled: props.disabled, readonly: props.readOnly, fullWidth: !props.inline, minDate: props.minDate, maxDate: props.maxDate, smartAutofocus: false, activator: InputDateActivator, onOpenChange: open => {
111
+ var _a;
112
+ isCalendarOpenRef.current = open;
113
+ // When calendar closes, fire onBlur if input is also not focused
114
+ if (!open &&
115
+ !inputFocusedRef.current &&
116
+ compositeFocusedRef.current &&
117
+ lastBlurEventRef.current) {
118
+ compositeFocusedRef.current = false;
119
+ (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, lastBlurEventRef.current);
120
+ }
121
+ } }));
107
122
  function InputDateActivator(activatorProps) {
108
123
  const { onClick, value } = activatorProps;
109
124
  const { handleChange, handleFocus, handleBlur, isFocused } = useInputDateActivatorActions({
110
125
  onChange: activatorProps.onChange,
111
126
  onFocus: event => {
112
127
  var _a, _b;
113
- (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, event);
128
+ inputFocusedRef.current = true;
129
+ // Fire parent's onFocus only when the composite component first receives focus
130
+ if (!compositeFocusedRef.current) {
131
+ compositeFocusedRef.current = true;
132
+ (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, event);
133
+ }
114
134
  (_b = activatorProps.onFocus) === null || _b === void 0 ? void 0 : _b.call(activatorProps);
115
135
  },
116
136
  onBlur: event => {
117
137
  var _a, _b;
118
- (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, event);
138
+ inputFocusedRef.current = false;
139
+ lastBlurEventRef.current = event;
140
+ // Only fire parent's onBlur if calendar is also closed
141
+ if (!isCalendarOpenRef.current && compositeFocusedRef.current) {
142
+ compositeFocusedRef.current = false;
143
+ (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, event);
144
+ }
119
145
  (_b = activatorProps.onBlur) === null || _b === void 0 ? void 0 : _b.call(activatorProps);
120
146
  },
121
147
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "6.105.1",
3
+ "version": "6.105.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -538,5 +538,5 @@
538
538
  "> 1%",
539
539
  "IE 10"
540
540
  ],
541
- "gitHead": "2e40c551d4af9f4de5d134287b55928b73a518b9"
541
+ "gitHead": "a4b58acea68d4e33629e47aba6f812c2c1259d96"
542
542
  }