@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.
@@ -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 dissapears when the input is not empty
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 || false);
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
- onSubmitKeyPress(key, () => {
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
- onSubmitKeyPress(key, () => {
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], {
@@ -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, type TextareaHTMLAttributes } from 'react';
2
- export type TextareaAutosizeProps = Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'children' | 'rows'> & {
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.31.3",
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": "17003345864c877b3029e00f63664c66ca1fd3f1",
66
+ "gitHead": "a917668414b5d0e1dc46512bd579e9cc958b51ea",
67
67
  "module": "lib-esm/index.js",
68
68
  "main": "lib-esm/index.js",
69
69
  "exports": {