@homebound/beam 2.298.1 → 2.298.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.
|
@@ -5,9 +5,6 @@ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
|
|
|
5
5
|
const Css_1 = require("../../../Css");
|
|
6
6
|
// Small wrapper around DatePicker to provide necessary styling and state handling when displayed as an overlay.
|
|
7
7
|
function DatePickerOverlay({ overlayProps, children }) {
|
|
8
|
-
return (
|
|
9
|
-
// Adds `tabIndex` so clicking within the DatePicker will provide a `e.relatedTarget` on blur and focus events.
|
|
10
|
-
// This allows for components such as the DateField to conditionally trigger their 'onBlur' prop. E.g. If the user leaves the field to interact with the DatePicker, then don't call onBlur
|
|
11
|
-
(0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.br4.bshModal.$, ...overlayProps, tabIndex: 0, children: children }));
|
|
8
|
+
return ((0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.br4.bshModal.$, ...overlayProps, children: children }));
|
|
12
9
|
}
|
|
13
10
|
exports.DatePickerOverlay = DatePickerOverlay;
|
|
@@ -24,12 +24,13 @@ function DateFieldBase(props) {
|
|
|
24
24
|
const inputWrapRef = (0, react_1.useRef)(null);
|
|
25
25
|
const buttonRef = (0, react_1.useRef)(null);
|
|
26
26
|
const overlayRef = (0, react_1.useRef)(null);
|
|
27
|
-
// Local focus ref
|
|
28
|
-
// E.g. If the picker closes due to focus going back to the input field then don't call onBlur. Also used to avoid updating WIP values
|
|
27
|
+
// Local focus ref used to avoid updating WIP values
|
|
29
28
|
const isFocused = (0, react_1.useRef)(false);
|
|
29
|
+
// Ref helper to identify when focus is returned to the TextField due to the DatePicker closing.
|
|
30
|
+
const closingDatePicker = (0, react_1.useRef)(false);
|
|
30
31
|
const dateFormat = (0, utils_1.getDateFormat)(format);
|
|
31
32
|
// The `wipValue` allows the "range" mode to set the value to `undefined`, even if the `onChange` response cannot be undefined.
|
|
32
|
-
// This makes working within the DateRangePicker much more user
|
|
33
|
+
// This makes working within the DateRangePicker much more user-friendly.
|
|
33
34
|
const [wipValue, setWipValue] = (0, react_1.useState)(value);
|
|
34
35
|
const [inputValue, setInputValue] = (0, react_1.useState)((_a = (isRangeMode ? (0, utils_1.formatDateRange)(props.value, dateFormat) : (0, utils_1.formatDate)(props.value, dateFormat))) !== null && _a !== void 0 ? _a : "");
|
|
35
36
|
const tid = (0, utils_2.useTestIds)(props, (0, defaultTestId_1.defaultTestId)(label));
|
|
@@ -43,23 +44,24 @@ function DateFieldBase(props) {
|
|
|
43
44
|
"aria-haspopup": "dialog",
|
|
44
45
|
value: inputValue,
|
|
45
46
|
};
|
|
46
|
-
const state = (0, react_stately_1.useOverlayTriggerState)({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
(0, utils_2.maybeCall)(onBlur);
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
isOpen: defaultOpen,
|
|
55
|
-
});
|
|
47
|
+
const state = (0, react_stately_1.useOverlayTriggerState)({ isOpen: defaultOpen });
|
|
48
|
+
const onPickerClose = (0, react_1.useCallback)(() => {
|
|
49
|
+
closingDatePicker.current = true;
|
|
50
|
+
state.close();
|
|
51
|
+
}, [state]);
|
|
56
52
|
const { labelProps, inputProps } = (0, react_aria_1.useTextField)({
|
|
57
53
|
...textFieldProps,
|
|
54
|
+
// Setting `inputMode` to none. This disables the virtual keyboard from being triggered on touch devices
|
|
55
|
+
inputMode: "none",
|
|
58
56
|
onFocus: () => {
|
|
59
57
|
var _a;
|
|
60
|
-
// Open overlay on focus of the input.
|
|
61
58
|
isFocused.current = true;
|
|
62
|
-
|
|
59
|
+
// Open overlay on focus of the input, only if the focus is not triggered due to the overlay being closed.
|
|
60
|
+
if (!closingDatePicker.current) {
|
|
61
|
+
state.open();
|
|
62
|
+
}
|
|
63
|
+
// Reset the closingDatePicker ref to false, so that the overlay can be opened again on the next focus event
|
|
64
|
+
closingDatePicker.current = false;
|
|
63
65
|
(0, utils_2.maybeCall)(onFocus);
|
|
64
66
|
if (wipValue && dateFormat !== utils_1.dateFormats.short) {
|
|
65
67
|
// When focused, change to use the "short" date format, as it is simpler to update by hand and parse.
|
|
@@ -70,13 +72,15 @@ function DateFieldBase(props) {
|
|
|
70
72
|
},
|
|
71
73
|
onBlur: (e) => {
|
|
72
74
|
var _a, _b;
|
|
75
|
+
// Resets the ref variables when the input loses focus.
|
|
73
76
|
isFocused.current = false;
|
|
74
|
-
|
|
75
|
-
//
|
|
77
|
+
closingDatePicker.current = false;
|
|
78
|
+
// If interacting with the overlay or the input, then assume the user is still working within the DatePicker and return early to not trigger onBlur functionality.
|
|
76
79
|
if ((inputWrapRef.current && inputWrapRef.current.contains(e.relatedTarget)) ||
|
|
77
80
|
(overlayRef.current && overlayRef.current.contains(e.relatedTarget))) {
|
|
78
81
|
return;
|
|
79
82
|
}
|
|
83
|
+
// Otherwise, if we are actually leaving the DatePicker component, then
|
|
80
84
|
const parsedDate = isRangeMode
|
|
81
85
|
? (0, utils_1.parseDateRange)(inputValue, utils_1.dateFormats.short)
|
|
82
86
|
: (0, utils_1.parseDate)(inputValue, utils_1.dateFormats.short);
|
|
@@ -89,8 +93,7 @@ function DateFieldBase(props) {
|
|
|
89
93
|
// Or if we need to reset the dateFormat back from `short` to whatever the user specified
|
|
90
94
|
setInputValue((_b = (isRangeMode ? (0, utils_1.formatDateRange)(props.value, dateFormat) : (0, utils_1.formatDate)(props.value, dateFormat))) !== null && _b !== void 0 ? _b : "");
|
|
91
95
|
}
|
|
92
|
-
|
|
93
|
-
// Only call `onBlur` if the overlay is closed. In other cases, the overlay's `onOpenChange` will handling calling `onBlur` when closing and the focus is not still on the input.
|
|
96
|
+
// Only call `onBlur` if the DatePicker is closed, meaning the user has actually left the DateField component.
|
|
94
97
|
if (!state.isOpen) {
|
|
95
98
|
(0, utils_2.maybeCall)(onBlur);
|
|
96
99
|
}
|
|
@@ -107,16 +110,15 @@ function DateFieldBase(props) {
|
|
|
107
110
|
const { buttonProps } = (0, react_aria_1.useButton)({
|
|
108
111
|
...triggerProps,
|
|
109
112
|
isDisabled: isDisabled || isReadOnly,
|
|
110
|
-
// When pressed
|
|
113
|
+
// When pressed then move focus the input, which will select the text and trigger the DatePicker to open
|
|
111
114
|
onPress: () => { var _a; return (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); },
|
|
112
|
-
onFocus: () => { var _a; return (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); },
|
|
113
115
|
}, buttonRef);
|
|
114
116
|
const { overlayProps: positionProps } = (0, react_aria_1.useOverlayPosition)({
|
|
115
117
|
targetRef: inputWrapRef,
|
|
116
118
|
overlayRef,
|
|
117
119
|
shouldFlip: true,
|
|
118
120
|
isOpen: state.isOpen,
|
|
119
|
-
onClose:
|
|
121
|
+
onClose: onPickerClose,
|
|
120
122
|
placement: "bottom left",
|
|
121
123
|
shouldUpdatePosition: true,
|
|
122
124
|
offset: 4,
|
|
@@ -164,9 +166,9 @@ function DateFieldBase(props) {
|
|
|
164
166
|
} })) }));
|
|
165
167
|
const calendarButton = ((0, jsx_runtime_1.jsx)("button", { ref: buttonRef, ...buttonProps, disabled: isDisabled, css: Css_1.Css.if(isDisabled).cursorNotAllowed.$, tabIndex: -1, ...tid.calendarButton, children: (0, jsx_runtime_1.jsx)(components_1.Icon, { icon: "calendar", color: isDisabled ? Css_1.Palette.Gray400 : Css_1.Palette.Gray700 }) }));
|
|
166
168
|
const EndFieldButtons = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isRangeFilterField && clearButton, !hideCalendarIcon && calendarButton] }));
|
|
167
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, { ...textFieldProps, errorMsg: errorMsg, helperText: helperText, required: required, labelProps: labelProps, inputProps: { ...inputProps, size: inputSize }, inputRef: inputRef, inputWrapRef: inputWrapRef, onChange: (v) => {
|
|
169
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(TextFieldBase_1.TextFieldBase, { ...textFieldProps, ...{ internalProps: { forceFocus: state.isOpen } }, errorMsg: errorMsg, helperText: helperText, required: required, labelProps: labelProps, inputProps: { ...inputProps, size: inputSize }, inputRef: inputRef, inputWrapRef: inputWrapRef, onChange: (v) => {
|
|
168
170
|
// hide the calendar if the user is manually entering the date
|
|
169
|
-
|
|
171
|
+
onPickerClose();
|
|
170
172
|
if (v) {
|
|
171
173
|
setInputValue(v);
|
|
172
174
|
// If changing the value directly (vs using the DatePicker), then we always use the short format
|
|
@@ -177,17 +179,17 @@ function DateFieldBase(props) {
|
|
|
177
179
|
else if (v === undefined) {
|
|
178
180
|
setInputValue("");
|
|
179
181
|
}
|
|
180
|
-
}, endAdornment: !iconLeft && EndFieldButtons, startAdornment: !hideCalendarIcon && iconLeft && calendarButton, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), ...others }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: inputWrapRef, popoverRef: overlayRef, positionProps: positionProps, onClose:
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
182
|
+
}, endAdornment: !iconLeft && EndFieldButtons, startAdornment: !hideCalendarIcon && iconLeft && calendarButton, tooltip: (0, components_1.resolveTooltip)(disabled, undefined, readOnly), ...others }), state.isOpen && ((0, jsx_runtime_1.jsx)(internal_1.Popover, { triggerRef: inputWrapRef, popoverRef: overlayRef, positionProps: positionProps, onClose: onPickerClose, isOpen: state.isOpen, children: (0, jsx_runtime_1.jsx)(react_aria_1.FocusScope, { autoFocus: true, restoreFocus: true, children: (0, jsx_runtime_1.jsx)(DatePickerOverlay_1.DatePickerOverlay, { overlayProps: overlayProps, children: isRangeMode ? ((0, jsx_runtime_1.jsx)(internal_1.DateRangePicker, { range: wipValue, disabledDays: disabledDays, onSelect: (dr) => {
|
|
183
|
+
var _a;
|
|
184
|
+
// Note: Do not close date range picker on select to allow the user to select multiple dates at a time
|
|
185
|
+
setInputValue((_a = (0, utils_1.formatDateRange)(dr, utils_1.dateFormats.short)) !== null && _a !== void 0 ? _a : "");
|
|
186
|
+
onChange(dr);
|
|
187
|
+
}, useYearPicker: isRangeFilterField, ...tid.datePicker })) : ((0, jsx_runtime_1.jsx)(internal_1.DatePicker, { value: wipValue, disabledDays: disabledDays, onSelect: (d) => {
|
|
188
|
+
var _a;
|
|
189
|
+
setInputValue((_a = (0, utils_1.formatDate)(d, utils_1.dateFormats.short)) !== null && _a !== void 0 ? _a : "");
|
|
190
|
+
onChange(d);
|
|
191
|
+
onPickerClose();
|
|
192
|
+
}, ...tid.datePicker })) }) }) }))] }));
|
|
191
193
|
}
|
|
192
194
|
exports.DateFieldBase = DateFieldBase;
|
|
193
195
|
function isParsedDateValid(d) {
|
|
@@ -111,9 +111,7 @@ function TextFieldBase(props) {
|
|
|
111
111
|
// Only show error styles if the field is not disabled, following the pattern that the error message is also hidden
|
|
112
112
|
...(errorMsg && !inputProps.disabled ? fieldStyles.error : {}),
|
|
113
113
|
...Css_1.Css.if(multiline).aifs.px0.mhPx(textAreaMinHeight).$,
|
|
114
|
-
}, ...hoverProps, ref: inputWrapRef, children: [!multiline && labelStyle === "inline" && label && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, { labelProps: labelProps, label: label, ...tid.label })), !multiline && startAdornment && (0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.fs0.br4.pr1.$, children: startAdornment }), (0, jsx_runtime_1.jsx)(ElementType, { ...(0, react_aria_1.mergeProps)(inputProps, { onBlur, onFocus: onFocusChained, onChange: onDomChange }, { "aria-invalid": Boolean(errorMsg), ...(labelStyle === "hidden" ? { "aria-label": label } : {}) }), ...(errorMsg ? { "aria-errormessage": errorMessageId } : {}), ref: fieldRef, rows: multiline ? 1 : undefined,
|
|
115
|
-
// Make the input field readOnly if the field explicitly sets it to `true`
|
|
116
|
-
readOnly: inputProps.readOnly, css: {
|
|
114
|
+
}, ...hoverProps, ref: inputWrapRef, children: [!multiline && labelStyle === "inline" && label && ((0, jsx_runtime_1.jsx)(Label_1.InlineLabel, { labelProps: labelProps, label: label, ...tid.label })), !multiline && startAdornment && (0, jsx_runtime_1.jsx)("span", { css: Css_1.Css.df.aic.fs0.br4.pr1.$, children: startAdornment }), (0, jsx_runtime_1.jsx)(ElementType, { ...(0, react_aria_1.mergeProps)(inputProps, { onBlur, onFocus: onFocusChained, onChange: onDomChange }, { "aria-invalid": Boolean(errorMsg), ...(labelStyle === "hidden" ? { "aria-label": label } : {}) }), ...(errorMsg ? { "aria-errormessage": errorMessageId } : {}), ref: fieldRef, rows: multiline ? 1 : undefined, css: {
|
|
117
115
|
...fieldStyles.input,
|
|
118
116
|
...(inputProps.disabled ? fieldStyles.disabled : {}),
|
|
119
117
|
...(showHover ? fieldStyles.hover : {}),
|