@box/blueprint-web 7.31.3 → 7.32.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.
- package/lib-esm/combobox/combobox.js +6 -0
- package/lib-esm/combobox/types.d.ts +3 -2
- package/lib-esm/content-field/content-field.js +4 -0
- package/lib-esm/date-picker/date-picker.js +18 -10
- package/lib-esm/primitives/base-text-input/base-text-input.js +4 -3
- package/lib-esm/select/select.js +6 -0
- package/lib-esm/text-area/text-area-autosize/types.d.ts +2 -2
- package/lib-esm/text-area/text-area.js +6 -0
- package/package.json +2 -2
|
@@ -242,6 +242,10 @@ const RootInner = ({
|
|
|
242
242
|
const showComboboxCancelButton = clearButtonAriaLabel && (inputValue.length > 0 || (Array.isArray(selectedValue) ? selectedValue.length > 0 : !!selectedValue));
|
|
243
243
|
const showSingleSelectChip = showComboboxCancelButton && !Array.isArray(selectedValue) && !!selectedValue;
|
|
244
244
|
const Label = useLabelable(label, comboboxId);
|
|
245
|
+
const inlineErrorId = useUniqueId('inline-error-');
|
|
246
|
+
const ariaDescribedBy = clsx(rest['aria-describedby'], {
|
|
247
|
+
[inlineErrorId]: hasError
|
|
248
|
+
});
|
|
245
249
|
const inputComponent = isInput ? jsxs(Fragment, {
|
|
246
250
|
children: [jsx(Label, {
|
|
247
251
|
className: clsx(styles.label, {
|
|
@@ -272,6 +276,7 @@ const RootInner = ({
|
|
|
272
276
|
children: [jsx(Combobox$1, {
|
|
273
277
|
...comboboxProps,
|
|
274
278
|
ref: reference,
|
|
279
|
+
"aria-describedby": ariaDescribedBy,
|
|
275
280
|
"aria-invalid": hasError,
|
|
276
281
|
"aria-required": required,
|
|
277
282
|
autoSelect: false,
|
|
@@ -301,6 +306,7 @@ const RootInner = ({
|
|
|
301
306
|
})
|
|
302
307
|
}), jsx(InlineError, {
|
|
303
308
|
className: styles.inlineError,
|
|
309
|
+
id: inlineErrorId,
|
|
304
310
|
children: error
|
|
305
311
|
})]
|
|
306
312
|
}) : jsx(Combobox$1, {
|
|
@@ -191,15 +191,16 @@ export interface ComboboxBaseProps<Multiple extends boolean, FreeInput extends b
|
|
|
191
191
|
clearButtonAriaLabel?: string;
|
|
192
192
|
/**
|
|
193
193
|
* Instance of an icon to be rendered at the end of the combobox input. When used in combination with `clearButtonAriaLabel`,
|
|
194
|
-
* it
|
|
194
|
+
* it disappears when the input is not empty
|
|
195
195
|
*/
|
|
196
196
|
endComboboxIcon?: React.ReactNode;
|
|
197
197
|
}
|
|
198
|
-
export type ComboboxTextArea = Pick<TextAreaProps, 'maxRows' | 'minRows' | 'maxLength'> & {
|
|
198
|
+
export type ComboboxTextArea = Pick<TextAreaProps, 'maxRows' | 'minRows' | 'maxLength' | 'aria-describedby'> & {
|
|
199
199
|
as: 'textarea';
|
|
200
200
|
};
|
|
201
201
|
export type ConditionalComboboxProps = ComboboxTextArea | {
|
|
202
202
|
as: 'input';
|
|
203
|
+
'aria-describedby'?: string;
|
|
203
204
|
};
|
|
204
205
|
export type ComboboxProps<Multiple extends boolean, FreeInput extends boolean, T extends OptionValue> = ComboboxBaseProps<Multiple, FreeInput, T> & ConditionalComboboxProps;
|
|
205
206
|
export interface ComboboxOptionProps extends Pick<SelectItemProps, 'hideOnClick' | 'onClick'> {
|
|
@@ -7,6 +7,7 @@ import clsx from 'clsx';
|
|
|
7
7
|
import { forwardRef, createRef } from 'react';
|
|
8
8
|
import { InlineError } from '../primitives/inline-error/inline-error.js';
|
|
9
9
|
import { useFullTextTooltip } from '../utils/useFullTextTooltip.js';
|
|
10
|
+
import { useUniqueId } from '../utils/useUniqueId.js';
|
|
10
11
|
import styles from './content-field.module.js';
|
|
11
12
|
import { messages } from './messages.js';
|
|
12
13
|
|
|
@@ -65,6 +66,7 @@ const ContentField = /*#__PURE__*/forwardRef(({
|
|
|
65
66
|
ref: labelRef,
|
|
66
67
|
textValue: title ?? hintText
|
|
67
68
|
});
|
|
69
|
+
const inlineErrorId = useUniqueId('inline-error-');
|
|
68
70
|
return jsxs("div", {
|
|
69
71
|
className: styles.contentFieldWrapper,
|
|
70
72
|
children: [jsxs("div", {
|
|
@@ -73,6 +75,7 @@ const ContentField = /*#__PURE__*/forwardRef(({
|
|
|
73
75
|
...wrapperProps,
|
|
74
76
|
children: jsxs(Button, {
|
|
75
77
|
ref: forwardedRef,
|
|
78
|
+
"aria-describedby": inlineErrorId,
|
|
76
79
|
className: clsx(styles.contentButton, {
|
|
77
80
|
[styles.hasSelection]: title,
|
|
78
81
|
[styles.error]: !!error
|
|
@@ -111,6 +114,7 @@ const ContentField = /*#__PURE__*/forwardRef(({
|
|
|
111
114
|
})]
|
|
112
115
|
}), jsx(InlineError, {
|
|
113
116
|
className: styles.inlineError,
|
|
117
|
+
id: inlineErrorId,
|
|
114
118
|
children: error
|
|
115
119
|
})]
|
|
116
120
|
});
|
|
@@ -9,6 +9,7 @@ import { Calendar as Calendar$1 } from '../primitives/calendar/calendar.js';
|
|
|
9
9
|
import '@internationalized/date';
|
|
10
10
|
import { IconButton } from '../primitives/icon-button/icon-button.js';
|
|
11
11
|
import { InlineError } from '../primitives/inline-error/inline-error.js';
|
|
12
|
+
import { useUniqueId } from '../utils/useUniqueId.js';
|
|
12
13
|
import { useLabelable } from '../util-components/labelable/useLabelable.js';
|
|
13
14
|
import styles from './date-picker.module.js';
|
|
14
15
|
|
|
@@ -18,6 +19,12 @@ const XMarkIcon = label => () => jsx(XMark, {
|
|
|
18
19
|
height: Size4,
|
|
19
20
|
width: Size4
|
|
20
21
|
});
|
|
22
|
+
const handleSubmitKeyPress = (key, callback) => {
|
|
23
|
+
const submitKeys = [' ', 'Enter'];
|
|
24
|
+
if (submitKeys.includes(key)) {
|
|
25
|
+
callback();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
21
28
|
const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
22
29
|
const {
|
|
23
30
|
className,
|
|
@@ -29,7 +36,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
29
36
|
openCalendarDropdownAriaLabel,
|
|
30
37
|
clearDatePickerAriaLabel,
|
|
31
38
|
error,
|
|
32
|
-
defaultOpen,
|
|
39
|
+
defaultOpen = false,
|
|
33
40
|
isDisabled,
|
|
34
41
|
calendarAriaLabel,
|
|
35
42
|
nextMonthAriaLabel,
|
|
@@ -43,7 +50,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
43
50
|
setInternalValue(value);
|
|
44
51
|
}
|
|
45
52
|
}, [value]);
|
|
46
|
-
const [isCalendarOpen, setIsCalendarOpen] = useState(defaultOpen
|
|
53
|
+
const [isCalendarOpen, setIsCalendarOpen] = useState(defaultOpen);
|
|
47
54
|
const firstDateSegmentRef = useRef(null);
|
|
48
55
|
const calendarButtonRef = useRef(null);
|
|
49
56
|
const shouldFocusStayInInput = useRef(false);
|
|
@@ -63,12 +70,6 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
63
70
|
const onCalendarDateSelect = useCallback(() => {
|
|
64
71
|
setIsCalendarOpen(false);
|
|
65
72
|
}, []);
|
|
66
|
-
const onSubmitKeyPress = (key, callback) => {
|
|
67
|
-
const submitKeys = [' ', 'Enter'];
|
|
68
|
-
if (submitKeys.includes(key)) {
|
|
69
|
-
callback();
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
73
|
const onInputWhiteSpaceClick = useCallback(() => {
|
|
73
74
|
setIsCalendarOpen(true);
|
|
74
75
|
shouldFocusStayInInput.current = true;
|
|
@@ -80,7 +81,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
80
81
|
const onKeyUp = useCallback(({
|
|
81
82
|
key
|
|
82
83
|
}) => {
|
|
83
|
-
|
|
84
|
+
handleSubmitKeyPress(key, () => {
|
|
84
85
|
onClearInputButtonClicked();
|
|
85
86
|
firstDateSegmentRef.current?.focus();
|
|
86
87
|
});
|
|
@@ -88,7 +89,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
88
89
|
const onKeyUpButton = useCallback(({
|
|
89
90
|
key
|
|
90
91
|
}) => {
|
|
91
|
-
|
|
92
|
+
handleSubmitKeyPress(key, () => {
|
|
92
93
|
setIsCalendarOpen(!isCalendarOpen);
|
|
93
94
|
shouldFocusStayInInput.current = false;
|
|
94
95
|
});
|
|
@@ -111,16 +112,22 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
111
112
|
}, []);
|
|
112
113
|
const displayValue = value !== undefined ? value : internalValue;
|
|
113
114
|
const Label = useLabelable(label, '');
|
|
115
|
+
const inlineErrorId = useUniqueId('inline-error-');
|
|
116
|
+
const ariaDescribedBy = clsx(rest['aria-describedby'], {
|
|
117
|
+
[inlineErrorId]: hasError
|
|
118
|
+
});
|
|
114
119
|
return jsx(RadixPopover.Root, {
|
|
115
120
|
onOpenChange: setIsCalendarOpen,
|
|
116
121
|
open: isCalendarOpen,
|
|
117
122
|
children: jsxs(DatePicker$1, {
|
|
118
123
|
...rest,
|
|
119
124
|
ref: forwardedRef,
|
|
125
|
+
"aria-describedby": ariaDescribedBy,
|
|
120
126
|
className: clsx(styles.datePicker, {
|
|
121
127
|
[styles.disabled]: isDisabled
|
|
122
128
|
}, className),
|
|
123
129
|
isDisabled: isDisabled,
|
|
130
|
+
isInvalid: hasError,
|
|
124
131
|
onChange: onDatePickerValueChanged,
|
|
125
132
|
value: displayValue,
|
|
126
133
|
children: [jsx(Label, {
|
|
@@ -205,6 +212,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
205
212
|
})
|
|
206
213
|
}), jsx(InlineError, {
|
|
207
214
|
className: styles.inlineError,
|
|
215
|
+
id: inlineErrorId,
|
|
208
216
|
children: error
|
|
209
217
|
})]
|
|
210
218
|
})
|
|
@@ -31,6 +31,9 @@ const BaseTextInput = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
31
31
|
const inlineErrorId = useUniqueId('inline-error-');
|
|
32
32
|
const hasError = !!error && !disabled;
|
|
33
33
|
const shouldMarkError = (!!error || invalid) && !disabled;
|
|
34
|
+
const ariaDescribedBy = clsx(rest['aria-describedby'], {
|
|
35
|
+
[inlineErrorId]: hasError
|
|
36
|
+
});
|
|
34
37
|
const IconComponent = useMemo(() => icon && /*#__PURE__*/cloneElement(icon, {
|
|
35
38
|
className: clsx(icon.props?.className, styles.iconShared)
|
|
36
39
|
}), [icon]);
|
|
@@ -48,10 +51,8 @@ const BaseTextInput = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
48
51
|
hideLabel: hideLabel
|
|
49
52
|
}), jsx("input", {
|
|
50
53
|
...rest,
|
|
51
|
-
...(hasError && {
|
|
52
|
-
'aria-describedby': inlineErrorId
|
|
53
|
-
}),
|
|
54
54
|
ref: forwardedRef,
|
|
55
|
+
"aria-describedby": ariaDescribedBy,
|
|
55
56
|
"aria-invalid": shouldMarkError,
|
|
56
57
|
"aria-required": required,
|
|
57
58
|
className: clsx([styles.textInput], {
|
package/lib-esm/select/select.js
CHANGED
|
@@ -51,6 +51,10 @@ const Root = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
51
51
|
onOpenChange: handleOnChange
|
|
52
52
|
};
|
|
53
53
|
const Label = useLabelable(label, selectId);
|
|
54
|
+
const inlineErrorId = useUniqueId('inline-error-');
|
|
55
|
+
const ariaDescribedBy = clsx(triggerProps['aria-describedby'], {
|
|
56
|
+
[inlineErrorId]: hasError
|
|
57
|
+
});
|
|
54
58
|
return jsxs("div", {
|
|
55
59
|
className: clsx(styles.container, {
|
|
56
60
|
[styles.disabled]: disabled
|
|
@@ -63,6 +67,7 @@ const Root = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
63
67
|
children: [jsxs(SelectPrimitive.Trigger, {
|
|
64
68
|
...triggerProps,
|
|
65
69
|
ref: forwardedRef,
|
|
70
|
+
"aria-describedby": ariaDescribedBy,
|
|
66
71
|
...(hasError && {
|
|
67
72
|
'aria-invalid': 'true'
|
|
68
73
|
}),
|
|
@@ -81,6 +86,7 @@ const Root = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
81
86
|
}), children]
|
|
82
87
|
}), jsx(InlineError, {
|
|
83
88
|
className: styles.inlineError,
|
|
89
|
+
id: inlineErrorId,
|
|
84
90
|
children: error
|
|
85
91
|
})]
|
|
86
92
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Ref
|
|
2
|
-
export type TextareaAutosizeProps = Omit<
|
|
1
|
+
import { type Ref } from 'react';
|
|
2
|
+
export type TextareaAutosizeProps = Omit<React.ComponentPropsWithRef<'textarea'>, 'children' | 'rows'> & {
|
|
3
3
|
ref?: Ref<HTMLTextAreaElement>;
|
|
4
4
|
/**
|
|
5
5
|
* Maximum number of rows to display.
|
|
@@ -21,7 +21,11 @@ const TextArea = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
21
21
|
...rest
|
|
22
22
|
} = props;
|
|
23
23
|
const textAreaId = useUniqueId('text-area-');
|
|
24
|
+
const inlineErrorId = useUniqueId('inline-error-');
|
|
24
25
|
const hasError = !!error && !disabled;
|
|
26
|
+
const ariaDescribedBy = clsx(rest['aria-describedby'], {
|
|
27
|
+
[inlineErrorId]: hasError
|
|
28
|
+
});
|
|
25
29
|
const Label = useLabelable(label, textAreaId);
|
|
26
30
|
return jsxs("div", {
|
|
27
31
|
className: clsx([styles.textAreaContainer], {
|
|
@@ -36,6 +40,7 @@ const TextArea = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
36
40
|
}), jsx(TextAreaAutosize, {
|
|
37
41
|
...rest,
|
|
38
42
|
ref: forwardedRef,
|
|
43
|
+
"aria-describedby": ariaDescribedBy,
|
|
39
44
|
"aria-invalid": hasError,
|
|
40
45
|
"aria-required": required,
|
|
41
46
|
disabled: disabled,
|
|
@@ -47,6 +52,7 @@ const TextArea = /*#__PURE__*/forwardRef((props, forwardedRef) => {
|
|
|
47
52
|
required: required
|
|
48
53
|
}), jsx(InlineError, {
|
|
49
54
|
className: styles.inlineError,
|
|
55
|
+
id: inlineErrorId,
|
|
50
56
|
children: error
|
|
51
57
|
})]
|
|
52
58
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@box/blueprint-web",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.32.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"publishConfig": {
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"react-stately": "^3.31.1",
|
|
64
64
|
"tsx": "^4.16.5"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "a917668414b5d0e1dc46512bd579e9cc958b51ea",
|
|
67
67
|
"module": "lib-esm/index.js",
|
|
68
68
|
"main": "lib-esm/index.js",
|
|
69
69
|
"exports": {
|