@box/blueprint-web 17.13.0 → 17.14.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.
|
@@ -92,6 +92,7 @@ const RootInner = ({
|
|
|
92
92
|
idForLabel,
|
|
93
93
|
displaySingleSelectionAsChip = multiselect,
|
|
94
94
|
autoComplete,
|
|
95
|
+
virtualFocus = false,
|
|
95
96
|
...comboboxProps
|
|
96
97
|
} = rest;
|
|
97
98
|
const isInput = useMemo(() => as === 'input', [as]);
|
|
@@ -119,7 +120,7 @@ const RootInner = ({
|
|
|
119
120
|
open: open && !disabled,
|
|
120
121
|
setOpen: onOpenChange,
|
|
121
122
|
includesBaseElement: true,
|
|
122
|
-
virtualFocus
|
|
123
|
+
virtualFocus,
|
|
123
124
|
focusLoop
|
|
124
125
|
});
|
|
125
126
|
const {
|
|
@@ -209,6 +209,13 @@ export interface ComboboxBaseProps<Multiple extends boolean, FreeInput extends b
|
|
|
209
209
|
* @default true
|
|
210
210
|
*/
|
|
211
211
|
focusLoop?: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* When set to `true`, arrow keys highlight options with `aria-activedescendant` and keyboard focus
|
|
214
|
+
* stays on the input, so navigating the list never blurs the field. Useful when the input validates
|
|
215
|
+
* or reacts to losing focus. When `false`, DOM focus moves onto the options themselves.
|
|
216
|
+
* @default false
|
|
217
|
+
*/
|
|
218
|
+
virtualFocus?: boolean;
|
|
212
219
|
/**
|
|
213
220
|
* Callback used when combobox input/textarea is focused
|
|
214
221
|
*/
|
|
@@ -70,6 +70,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
70
70
|
});
|
|
71
71
|
const dateInputRef = useRef(null);
|
|
72
72
|
const calendarButtonRef = useRef(null);
|
|
73
|
+
const groupRef = useRef(null);
|
|
73
74
|
const shouldFocusStayInInput = useRef(autoFocus && isCalendarOpen);
|
|
74
75
|
const focusFirstDateSegment = useCallback(() => {
|
|
75
76
|
dateInputRef.current?.querySelector('[role="spinbutton"]')?.focus();
|
|
@@ -108,6 +109,23 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
108
109
|
setIsCalendarOpen(true);
|
|
109
110
|
shouldFocusStayInInput.current = true;
|
|
110
111
|
}, [setIsCalendarOpen]);
|
|
112
|
+
const onDateInputKeyDownCapture = useCallback(event => {
|
|
113
|
+
if (event.key !== 'Enter' || !isCalendarOpen) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const {
|
|
117
|
+
target
|
|
118
|
+
} = event;
|
|
119
|
+
if (!(target instanceof HTMLElement) || target.getAttribute('role') !== 'spinbutton') {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
event.preventDefault();
|
|
123
|
+
shouldFocusStayInInput.current = true;
|
|
124
|
+
setIsCalendarOpen(false);
|
|
125
|
+
}, [isCalendarOpen, setIsCalendarOpen]);
|
|
126
|
+
const onGroupFocusCapture = useCallback(() => {
|
|
127
|
+
shouldFocusStayInInput.current = true;
|
|
128
|
+
}, []);
|
|
111
129
|
const hasError = !!error && !isDisabled;
|
|
112
130
|
const calendarKey = `${internalValue?.day}/${internalValue?.month}/${internalValue?.year}${internalValue?.era}`;
|
|
113
131
|
const onOpenAutoFocus = useCallback(e => {
|
|
@@ -135,11 +153,8 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
135
153
|
calendarButtonRef.current?.focus();
|
|
136
154
|
}
|
|
137
155
|
}, [focusFirstDateSegment]);
|
|
138
|
-
const onFocusOutside = useCallback(
|
|
139
|
-
|
|
140
|
-
if (!wasCalendarButtonPressed) {
|
|
141
|
-
e.preventDefault();
|
|
142
|
-
}
|
|
156
|
+
const onFocusOutside = useCallback(event => {
|
|
157
|
+
event.preventDefault();
|
|
143
158
|
}, []);
|
|
144
159
|
const displayValue = value !== undefined ? value : internalValue;
|
|
145
160
|
const Label = useLabelable(label, '');
|
|
@@ -171,8 +186,10 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
171
186
|
}), jsx(RadixPopover.Anchor, {
|
|
172
187
|
asChild: true,
|
|
173
188
|
children: jsxs(Group, {
|
|
189
|
+
ref: groupRef,
|
|
174
190
|
className: clsx(styles.group),
|
|
175
191
|
"data-target-id": rest.dataTargetId,
|
|
192
|
+
onFocusCapture: onGroupFocusCapture,
|
|
176
193
|
children: [jsx("div", {
|
|
177
194
|
ref: dateInputRef,
|
|
178
195
|
className: clsx(styles.groupContainer, {
|
|
@@ -181,6 +198,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
181
198
|
"data-bp-animated": isAnimationEnabled ? 'true' : 'false',
|
|
182
199
|
"data-testid": "date-picker-input",
|
|
183
200
|
onClickCapture: onDateInputClick,
|
|
201
|
+
onKeyDownCapture: onDateInputKeyDownCapture,
|
|
184
202
|
children: jsx(DateInput, {
|
|
185
203
|
className: clsx(styles.groupContainerInput),
|
|
186
204
|
children: segment => jsx(DateSegment, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@box/blueprint-web",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.14.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@ariakit/react": "0.4.21",
|
|
57
57
|
"@ariakit/react-core": "0.4.21",
|
|
58
|
-
"@box/blueprint-web-assets": "^5.10.
|
|
58
|
+
"@box/blueprint-web-assets": "^5.10.19",
|
|
59
59
|
"@internationalized/date": "^3.12.0",
|
|
60
60
|
"@radix-ui/react-accordion": "1.1.2",
|
|
61
61
|
"@radix-ui/react-checkbox": "1.0.4",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@box/box-test-client": "^3.2.7",
|
|
88
88
|
"@box/playwright-utils": "^2.8.5",
|
|
89
|
-
"@box/storybook-utils": "^1.2.
|
|
89
|
+
"@box/storybook-utils": "^1.2.63",
|
|
90
90
|
"@figma/code-connect": "1.4.4",
|
|
91
91
|
"@playwright/test": "1.46.1",
|
|
92
92
|
"@types/js-yaml": "^4.0.9",
|