@box/blueprint-web 16.19.2 → 16.20.0
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.
|
@@ -11,6 +11,7 @@ import '@internationalized/date';
|
|
|
11
11
|
import { IconButton } from '../primitives/icon-button/icon-button.js';
|
|
12
12
|
import { InlineError } from '../primitives/inline-error/inline-error.js';
|
|
13
13
|
import { useLabelable } from '../util-components/labelable/useLabelable.js';
|
|
14
|
+
import { useControllableState } from '../utils/useControllableState.js';
|
|
14
15
|
import { useUniqueId } from '../utils/useUniqueId.js';
|
|
15
16
|
import styles from './date-picker.module.js';
|
|
16
17
|
|
|
@@ -38,6 +39,8 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
38
39
|
openCalendarDropdownAriaLabel,
|
|
39
40
|
clearDatePickerAriaLabel,
|
|
40
41
|
error,
|
|
42
|
+
isOpen: isOpenProp,
|
|
43
|
+
onOpenChange,
|
|
41
44
|
defaultOpen = false,
|
|
42
45
|
isDisabled,
|
|
43
46
|
calendarAriaLabel,
|
|
@@ -55,10 +58,17 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
55
58
|
setInternalValue(value);
|
|
56
59
|
}
|
|
57
60
|
}, [value]);
|
|
58
|
-
const [isCalendarOpen, setIsCalendarOpen] =
|
|
59
|
-
|
|
61
|
+
const [isCalendarOpen = false, setIsCalendarOpen] = useControllableState({
|
|
62
|
+
prop: isOpenProp,
|
|
63
|
+
defaultProp: defaultOpen,
|
|
64
|
+
onChange: onOpenChange
|
|
65
|
+
});
|
|
66
|
+
const dateInputRef = useRef(null);
|
|
60
67
|
const calendarButtonRef = useRef(null);
|
|
61
68
|
const shouldFocusStayInInput = useRef(false);
|
|
69
|
+
const focusFirstDateSegment = useCallback(() => {
|
|
70
|
+
dateInputRef.current?.querySelector('[role="spinbutton"]')?.focus();
|
|
71
|
+
}, []);
|
|
62
72
|
const onDatePickerValueChanged = useCallback(newValue => {
|
|
63
73
|
onChange?.(newValue);
|
|
64
74
|
if (value === undefined) {
|
|
@@ -73,23 +83,26 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
73
83
|
}, [onChange, value]);
|
|
74
84
|
const onCalendarDateSelect = useCallback(() => {
|
|
75
85
|
setIsCalendarOpen(false);
|
|
76
|
-
}, []);
|
|
86
|
+
}, [setIsCalendarOpen]);
|
|
77
87
|
const onPressCalendar = useCallback(() => {
|
|
78
|
-
setIsCalendarOpen(v => !v);
|
|
79
88
|
shouldFocusStayInInput.current = false;
|
|
80
|
-
|
|
89
|
+
setIsCalendarOpen(isOpen => !isOpen);
|
|
90
|
+
}, [setIsCalendarOpen]);
|
|
91
|
+
const onPopoverOpenChange = useCallback(isOpen => {
|
|
92
|
+
setIsCalendarOpen(isOpen);
|
|
93
|
+
}, [setIsCalendarOpen]);
|
|
81
94
|
const onClearButtonKeypress = useCallback(({
|
|
82
95
|
key
|
|
83
96
|
}) => {
|
|
84
97
|
handleSubmitKeyPress(key, () => {
|
|
85
98
|
onClearInputButtonClicked();
|
|
86
|
-
|
|
99
|
+
focusFirstDateSegment();
|
|
87
100
|
});
|
|
88
|
-
}, [onClearInputButtonClicked]);
|
|
101
|
+
}, [focusFirstDateSegment, onClearInputButtonClicked]);
|
|
89
102
|
const onDateInputClick = useCallback(() => {
|
|
90
103
|
setIsCalendarOpen(true);
|
|
91
104
|
shouldFocusStayInInput.current = true;
|
|
92
|
-
}, []);
|
|
105
|
+
}, [setIsCalendarOpen]);
|
|
93
106
|
const hasError = !!error && !isDisabled;
|
|
94
107
|
const calendarKey = `${internalValue?.day}/${internalValue?.month}/${internalValue?.year}${internalValue?.era}`;
|
|
95
108
|
const onOpenAutoFocus = useCallback(e => {
|
|
@@ -104,15 +117,19 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
104
117
|
} = document;
|
|
105
118
|
const isFocusLost = !activeElement || activeElement === document.body || activeElement === document.documentElement || isRadixFocusGuard(activeElement);
|
|
106
119
|
const focusAlreadyOutsidePopover = !isFocusLost && !(e.currentTarget instanceof Node && e.currentTarget.contains(activeElement));
|
|
120
|
+
// Clear after close-focus uses it so a later open does not keep suppressing autofocus,
|
|
121
|
+
// without racing Esc/date-select focus restore (which needs the flag during this callback).
|
|
122
|
+
const shouldKeepFocusInInput = shouldFocusStayInInput.current;
|
|
123
|
+
shouldFocusStayInInput.current = false;
|
|
107
124
|
if (focusAlreadyOutsidePopover) {
|
|
108
125
|
return;
|
|
109
126
|
}
|
|
110
|
-
if (
|
|
111
|
-
|
|
127
|
+
if (shouldKeepFocusInInput) {
|
|
128
|
+
focusFirstDateSegment();
|
|
112
129
|
} else {
|
|
113
130
|
calendarButtonRef.current?.focus();
|
|
114
131
|
}
|
|
115
|
-
}, []);
|
|
132
|
+
}, [focusFirstDateSegment]);
|
|
116
133
|
const onFocusOutside = useCallback(e => {
|
|
117
134
|
const wasCalendarButtonPressed = calendarButtonRef.current && calendarButtonRef.current.contains(e.target);
|
|
118
135
|
if (!wasCalendarButtonPressed) {
|
|
@@ -126,7 +143,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
126
143
|
[inlineErrorId]: hasError
|
|
127
144
|
});
|
|
128
145
|
return jsx(RadixPopover.Root, {
|
|
129
|
-
onOpenChange:
|
|
146
|
+
onOpenChange: onPopoverOpenChange,
|
|
130
147
|
open: isCalendarOpen,
|
|
131
148
|
children: jsxs(DatePicker$1, {
|
|
132
149
|
...rest,
|
|
@@ -151,6 +168,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
151
168
|
className: clsx(styles.group),
|
|
152
169
|
"data-target-id": rest.dataTargetId,
|
|
153
170
|
children: [jsx("div", {
|
|
171
|
+
ref: dateInputRef,
|
|
154
172
|
className: clsx(styles.groupContainer, {
|
|
155
173
|
[styles.error]: hasError
|
|
156
174
|
}),
|
|
@@ -159,11 +177,6 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
159
177
|
children: jsx(DateInput, {
|
|
160
178
|
className: clsx(styles.groupContainerInput),
|
|
161
179
|
children: segment => jsx(DateSegment, {
|
|
162
|
-
ref: node => {
|
|
163
|
-
if (!firstDateSegmentRef.current) {
|
|
164
|
-
firstDateSegmentRef.current = node;
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
180
|
className: styles.groupContainerInputSegment,
|
|
168
181
|
segment: segment
|
|
169
182
|
})
|
|
@@ -3,7 +3,7 @@ import { type CalendarBase } from '../primitives/calendar/types';
|
|
|
3
3
|
import { type InputValueProps } from '../types/input-value-props';
|
|
4
4
|
import { type Modify } from '../types/modify';
|
|
5
5
|
import { type Labelable } from '../util-components/labelable/types';
|
|
6
|
-
interface DatePickerPropsBase extends Omit<RACDatePickerProps<DateValue>, 'children'>, Labelable {
|
|
6
|
+
interface DatePickerPropsBase extends Omit<RACDatePickerProps<DateValue>, 'children' | 'isOpen' | 'onOpenChange' | 'defaultOpen'>, Labelable {
|
|
7
7
|
/**
|
|
8
8
|
* When `true`, label text is hidden.
|
|
9
9
|
*
|
|
@@ -23,7 +23,15 @@ interface DatePickerPropsBase extends Omit<RACDatePickerProps<DateValue>, 'child
|
|
|
23
23
|
*/
|
|
24
24
|
error?: React.ReactNode;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Controlled popover open state.
|
|
27
|
+
*/
|
|
28
|
+
isOpen?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Called when the calendar popover open state changes.
|
|
31
|
+
*/
|
|
32
|
+
onOpenChange?: (isOpen: boolean) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Controls whether calendar dialog is initially opened in uncontrolled mode.
|
|
27
35
|
*/
|
|
28
36
|
defaultOpen?: boolean;
|
|
29
37
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@box/blueprint-web",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.20.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@ariakit/react": "0.4.21",
|
|
52
52
|
"@ariakit/react-core": "0.4.21",
|
|
53
|
-
"@box/blueprint-web-assets": "^5.7.
|
|
53
|
+
"@box/blueprint-web-assets": "^5.7.7",
|
|
54
54
|
"@internationalized/date": "^3.12.0",
|
|
55
55
|
"@radix-ui/react-accordion": "1.1.2",
|
|
56
56
|
"@radix-ui/react-checkbox": "1.0.4",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"type-fest": "^3.2.0"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@box/storybook-utils": "^1.2.
|
|
82
|
+
"@box/storybook-utils": "^1.2.16",
|
|
83
83
|
"@figma/code-connect": "1.4.4",
|
|
84
84
|
"@types/react": "^18.0.0",
|
|
85
85
|
"@types/react-dom": "^18.0.0",
|