@box/blueprint-web 6.45.3 → 7.0.1

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,9 @@ import { type AccordionItemProps, type AccordionProps } from './types';
5
5
  *
6
6
  * @example
7
7
  * <Accordion>
8
- * <Accordion.Item id="1" value="item-1" title="Item 1"><div>1st item</div></Accordion.Item>
9
- * <Accordion.Item id="2" value="item-2" title="Item 2"><div>2nd item</div></Accordion.Item>
10
- * <Accordion.Item id="3" value="item-3" title="Item 3"><div>3rd item </div></Accordion.Item>
8
+ * <Accordion.Item value="item-1" title="Item 1"><div>1st item</div></Accordion.Item>
9
+ * <Accordion.Item value="item-2" title="Item 2"><div>2nd item</div></Accordion.Item>
10
+ * <Accordion.Item value="item-3" title="Item 3"><div>3rd item </div></Accordion.Item>
11
11
  * </Accordion>
12
12
  */
13
13
  export declare const Root: (props: AccordionProps) => JSX.Element;
@@ -13,9 +13,9 @@ import styles from './accordion.module.js';
13
13
  *
14
14
  * @example
15
15
  * <Accordion>
16
- * <Accordion.Item id="1" value="item-1" title="Item 1"><div>1st item</div></Accordion.Item>
17
- * <Accordion.Item id="2" value="item-2" title="Item 2"><div>2nd item</div></Accordion.Item>
18
- * <Accordion.Item id="3" value="item-3" title="Item 3"><div>3rd item </div></Accordion.Item>
16
+ * <Accordion.Item value="item-1" title="Item 1"><div>1st item</div></Accordion.Item>
17
+ * <Accordion.Item value="item-2" title="Item 2"><div>2nd item</div></Accordion.Item>
18
+ * <Accordion.Item value="item-3" title="Item 3"><div>3rd item </div></Accordion.Item>
19
19
  * </Accordion>
20
20
  */
21
21
  const Root = props => {
@@ -27,7 +27,6 @@ const Item = props => {
27
27
  const {
28
28
  loading,
29
29
  loadingAriaLabel,
30
- id,
31
30
  children,
32
31
  className,
33
32
  ...rest
@@ -8,11 +8,6 @@ interface Loading {
8
8
  loadingAriaLabel: string;
9
9
  }
10
10
  export type AccordionBaseItem = {
11
- /**
12
- * @deprecated
13
- * Content of the accordion item that is displayed when the section is expanded
14
- */
15
- id?: string;
16
11
  /**
17
12
  * Content of the accordion item that is displayed when the section is expanded
18
13
  */
@@ -72,7 +72,7 @@ const ChipsGroup = props => {
72
72
  // it is not the case for the Chips Group as per the a11y pattern. In this case, the error is false positive.
73
73
  __checkInteractivity: false,
74
74
  "aria-hidden": true,
75
- content: childElement.props.label,
75
+ content: childElement.props.tooltip ?? childElement.props.label,
76
76
  children: /*#__PURE__*/React__default.cloneElement(childElement, {
77
77
  // Register the InputChip reference
78
78
  ref: node => {
@@ -16,6 +16,14 @@ import styles from './combobox.module.js';
16
16
 
17
17
  const getOptionValue = option => typeof option === 'string' ? option : option.value;
18
18
  const getOptionFromValue = (value, options) => options.find(option => typeof option === 'string' ? option === value : option.value === value);
19
+ const getDisplayValueFromOptionValue = (optionValue, options, displayValue) => {
20
+ const option = getOptionFromValue(optionValue, options);
21
+ return displayValue && option ? displayValue(option) : optionValue;
22
+ };
23
+ const getTooltipValueFromOptionValue = (optionValue, options, displayTooltip) => {
24
+ const option = getOptionFromValue(optionValue, options);
25
+ return displayTooltip && option ? displayTooltip(option) : undefined;
26
+ };
19
27
  const RootInner = ({
20
28
  as = 'input',
21
29
  ...props
@@ -43,6 +51,7 @@ const RootInner = ({
43
51
  onValueChange,
44
52
  displayValue,
45
53
  displayAvatar,
54
+ displayTooltip,
46
55
  renderOption,
47
56
  options,
48
57
  filterFn,
@@ -129,12 +138,6 @@ const RootInner = ({
129
138
  }
130
139
  return visibleOptions.filter(option => !selectedValue.includes(getOptionValue(option)));
131
140
  }, [filterFn, options, hideSelectedOptions, inputValue, selectedValue]);
132
- const getDisplayValueFromOptionValue = useCallback(optionValue => {
133
- const option = getOptionFromValue(optionValue, options);
134
- return displayValue && option ? displayValue(option) : optionValue;
135
- },
136
- // eslint-disable-next-line react-hooks/exhaustive-deps
137
- [displayValue]);
138
141
  const getDisplayAvatarFromOptionValue = useCallback(optionValue => {
139
142
  const option = getOptionFromValue(optionValue, options);
140
143
  return displayAvatar && option ? displayAvatar(option) : undefined;
@@ -161,11 +164,13 @@ const RootInner = ({
161
164
  if (Array.isArray(selectedValueMemoized)) {
162
165
  setInputValue('');
163
166
  } else if (selectedValueMemoized) {
164
- setInputValue(getDisplayValueFromOptionValue(selectedValueMemoized));
167
+ setInputValue(getDisplayValueFromOptionValue(selectedValueMemoized, options, displayValue));
165
168
  // Also focus input for single-select variant
166
169
  focusInput();
167
170
  }
168
- }, [selectedValueMemoized, getDisplayValueFromOptionValue, setInputValue, focusInput]);
171
+ },
172
+ // eslint-disable-next-line react-hooks/exhaustive-deps
173
+ [selectedValueMemoized, setInputValue, focusInput]);
169
174
  const handleKeyDown = useCallback(event => {
170
175
  // Close menu
171
176
  if (event.key === 'Enter' || event.key === 'Tab') {
@@ -190,8 +195,10 @@ const RootInner = ({
190
195
  if (!clearOnBlur || isOpen) {
191
196
  return;
192
197
  }
193
- setInputValue(Array.isArray(selectedValue) ? '' : getDisplayValueFromOptionValue(selectedValue));
194
- }, [clearOnBlur, getDisplayValueFromOptionValue, isOpen, selectedValue, setInputValue]);
198
+ setInputValue(Array.isArray(selectedValue) ? '' : getDisplayValueFromOptionValue(selectedValue, options, displayValue));
199
+ },
200
+ // eslint-disable-next-line react-hooks/exhaustive-deps
201
+ [clearOnBlur, isOpen, selectedValue, setInputValue]);
195
202
  const removeInputChip = id => {
196
203
  // For multi-select variant only
197
204
  selectStore.setValue(prev => {
@@ -230,8 +237,9 @@ const RootInner = ({
230
237
  children: [showChipsGroup && jsx(ChipsGroup, {
231
238
  children: selectedValue.map(selected => jsx(InputChip, {
232
239
  avatar: getDisplayAvatarFromOptionValue(selected),
233
- label: getDisplayValueFromOptionValue(selected),
234
- onDelete: () => removeInputChip(selected)
240
+ label: getDisplayValueFromOptionValue(selected, options, displayValue),
241
+ onDelete: () => removeInputChip(selected),
242
+ tooltip: getTooltipValueFromOptionValue(selected, options, displayTooltip)
235
243
  }, selected))
236
244
  }), jsx("div", {
237
245
  className: styles.textInputWrapper,
@@ -86,6 +86,10 @@ export interface ComboboxBaseProps<Multiple extends boolean, FreeInput extends b
86
86
  * If not provided `displayValue()` is used to render select option item with a checkmark.
87
87
  */
88
88
  displayAvatar?: (option: T) => React.ReactElement | undefined;
89
+ /**
90
+ * Return a string representation of a tooltip displayed on hover of an Input Chip in Combobox.
91
+ */
92
+ displayTooltip?: (option: T) => string;
89
93
  /**
90
94
  * Return a JSX representations of an option displayed in Combobox dropdown
91
95
  * If not provided `displayValue()` is used to render select option item with a checkmark.
@@ -1,5 +1,3 @@
1
1
  /// <reference types="react" />
2
- import { type DateValue } from 'react-aria-components';
3
- export declare const DatePicker: import("react").ForwardRefExoticComponent<Omit<import("./types").DatePickerPropsBase, "onChange"> & {
4
- onChange: (value: DateValue | null) => void;
5
- } & import("../primitives/calendar/types").CalendarBase & import("react").RefAttributes<HTMLDivElement>>;
2
+ import { type DatePickerProps } from './types';
3
+ export declare const DatePicker: import("react").ForwardRefExoticComponent<DatePickerProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -3,7 +3,7 @@ import { Calendar, XMark } from '@box/blueprint-web-assets/icons/Fill';
3
3
  import { Gray65, Size4 } from '@box/blueprint-web-assets/tokens/tokens';
4
4
  import * as RadixPopover from '@radix-ui/react-popover';
5
5
  import clsx from 'clsx';
6
- import { forwardRef, useState, useRef, useCallback } from 'react';
6
+ import { forwardRef, useState, useEffect, useRef, useCallback } from 'react';
7
7
  import { DatePicker as DatePicker$1, Label, Group, DateInput, DateSegment, Button } from 'react-aria-components';
8
8
  import { Calendar as Calendar$1 } from '../primitives/calendar/calendar.js';
9
9
  import '@internationalized/date';
@@ -22,6 +22,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
22
22
  className,
23
23
  onChange,
24
24
  value,
25
+ defaultValue,
25
26
  label,
26
27
  openCalendarDropdownAriaLabel,
27
28
  clearDatePickerAriaLabel,
@@ -34,24 +35,32 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
34
35
  previousMonthAriaLabel,
35
36
  ...rest
36
37
  } = props;
37
- const [selectedDate, setSelectedDate] = useState(value);
38
+ const [internalValue, setInternalValue] = useState(defaultValue);
39
+ useEffect(() => {
40
+ if (value !== undefined) {
41
+ setInternalValue(value);
42
+ }
43
+ }, [value]);
38
44
  const [isCalendarOpen, setIsCalendarOpen] = useState(defaultOpen || false);
39
45
  const firstDateSegmentRef = useRef(null);
40
46
  const calendarButtonRef = useRef(null);
41
47
  const shouldFocusStayInInput = useRef(false);
42
48
  const onDatePickerValueChanged = useCallback(newValue => {
43
- setSelectedDate(newValue);
44
49
  onChange?.(newValue);
45
- }, [setSelectedDate, onChange]);
50
+ if (value === undefined) {
51
+ setInternalValue(newValue);
52
+ }
53
+ }, [onChange, value]);
46
54
  const onClearInputButtonClicked = useCallback(() => {
47
- setSelectedDate(null);
48
55
  onChange?.(null);
56
+ if (value === undefined) {
57
+ setInternalValue(null);
58
+ }
49
59
  firstDateSegmentRef.current?.focus();
50
- }, [onChange]);
51
- const onCalendarDateSelect = useCallback(e => {
52
- onDatePickerValueChanged(e);
60
+ }, [onChange, value]);
61
+ const onCalendarDateSelect = useCallback(() => {
53
62
  setIsCalendarOpen(false);
54
- }, [onDatePickerValueChanged]);
63
+ }, []);
55
64
  const onSubmitKeyPress = (key, callback) => {
56
65
  const submitKeys = [' ', 'Enter'];
57
66
  if (submitKeys.includes(key)) {
@@ -86,7 +95,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
86
95
  shouldFocusStayInInput.current = false;
87
96
  }, []);
88
97
  const hasError = !!error && !isDisabled;
89
- const calendarKey = `${selectedDate?.day}/${selectedDate?.month}/${selectedDate?.year}${selectedDate?.era}`;
98
+ const calendarKey = `${internalValue?.day}/${internalValue?.month}/${internalValue?.year}${internalValue?.era}`;
90
99
  const onOpenAutoFocus = useCallback(e => {
91
100
  if (shouldFocusStayInInput.current) {
92
101
  e.preventDefault();
@@ -98,6 +107,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
98
107
  e.preventDefault();
99
108
  }
100
109
  }, []);
110
+ const displayValue = value !== undefined ? value : internalValue;
101
111
  return jsx(RadixPopover.Root, {
102
112
  onOpenChange: setIsCalendarOpen,
103
113
  open: isCalendarOpen,
@@ -109,7 +119,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
109
119
  }, className),
110
120
  isDisabled: isDisabled,
111
121
  onChange: onDatePickerValueChanged,
112
- value: selectedDate,
122
+ value: displayValue,
113
123
  children: [jsx(Label, {
114
124
  className: clsx(styles.label, {
115
125
  [styles.disabled]: isDisabled
@@ -137,7 +147,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
137
147
  segment: segment
138
148
  })
139
149
  })
140
- }), selectedDate && jsx(IconButton, {
150
+ }), displayValue && jsx(IconButton, {
141
151
  "aria-label": clearDatePickerAriaLabel,
142
152
  className: clsx(styles.button, styles.clear),
143
153
  disabled: isDisabled,
@@ -187,7 +197,7 @@ const DatePicker = /*#__PURE__*/forwardRef((props, forwardedRef) => {
187
197
  nextMonthAriaLabel: nextMonthAriaLabel,
188
198
  onChange: onCalendarDateSelect,
189
199
  previousMonthAriaLabel: previousMonthAriaLabel,
190
- value: selectedDate
200
+ value: displayValue
191
201
  }, calendarKey)
192
202
  })
193
203
  }), jsx(InlineError, {
@@ -1,8 +1,9 @@
1
1
  /// <reference types="react" />
2
2
  import { type DatePickerProps as RACDatePickerProps, type DateValue } from 'react-aria-components';
3
3
  import { type CalendarBase } from '../primitives/calendar/types';
4
+ import { type InputValueProps } from '../types/input-value-props';
4
5
  import { type Modify } from '../types/modify';
5
- export interface DatePickerPropsBase extends Omit<RACDatePickerProps<DateValue>, 'children'> {
6
+ interface DatePickerPropsBase extends Omit<RACDatePickerProps<DateValue>, 'children'> {
6
7
  /**
7
8
  * Label displayed above date-picker input
8
9
  */
@@ -28,9 +29,5 @@ export interface DatePickerPropsBase extends Omit<RACDatePickerProps<DateValue>,
28
29
  */
29
30
  portalElement?: HTMLElement;
30
31
  }
31
- export type DatePickerProps = Modify<DatePickerPropsBase, {
32
- /**
33
- * Callback invoked once DatePicker value changes
34
- */
35
- onChange: (value: DateValue | null) => void;
36
- }> & CalendarBase;
32
+ export type DatePickerProps = Modify<DatePickerPropsBase, InputValueProps<DateValue>> & CalendarBase;
33
+ export {};
package/lib-esm/index.css CHANGED
@@ -3581,7 +3581,7 @@ table.bp_inline_table_module_inlineTable--b023b tr:not(:last-child) td{
3581
3581
  border-block-end:var(--border-1) solid var(--gray-10);
3582
3582
  }
3583
3583
 
3584
- .bp_modal_module_overlay--925a9{
3584
+ .bp_modal_module_overlay--aef1e{
3585
3585
  background-color:var(--black-opacity-80);
3586
3586
  bottom:0;
3587
3587
  display:grid;
@@ -3592,94 +3592,106 @@ table.bp_inline_table_module_inlineTable--b023b tr:not(:last-child) td{
3592
3592
  top:0;
3593
3593
  z-index:370;
3594
3594
  }
3595
- @media (min-width: 460px){
3596
- .bp_modal_module_overlay--925a9{
3595
+ @media (width > 459px){
3596
+ .bp_modal_module_overlay--aef1e{
3597
3597
  place-items:center;
3598
3598
  }
3599
3599
  }
3600
3600
 
3601
- .bp_modal_module_content--925a9{
3602
- animation:bp_modal_module_popup_bounce_in--925a9 var(--animation-duration-3);
3601
+ .bp_modal_module_content--aef1e{
3602
+ animation:bp_modal_module_popup_bounce_in--aef1e var(--animation-duration-3);
3603
3603
  background-color:var(--gray-white);
3604
3604
  display:flex;
3605
3605
  flex-direction:column;
3606
3606
  height:100vh;
3607
- max-width:48rem;
3608
3607
  overflow:hidden;
3609
3608
  position:relative;
3610
3609
  }
3611
- @media (min-width: 460px){
3612
- .bp_modal_module_content--925a9{
3610
+ @media (width > 459px){
3611
+ .bp_modal_module_content--aef1e{
3613
3612
  border-radius:var(--radius-4);
3614
3613
  height:auto;
3615
3614
  margin:0 var(--space-8);
3616
3615
  max-height:calc(100vh - var(--space-8)*2);
3616
+ min-width:calc(460px - var(--space-8)*2);
3617
+ }
3618
+ .bp_modal_module_content--aef1e.bp_modal_module_smallSizeModal--aef1e{
3619
+ max-width:460px;
3620
+ }
3621
+ .bp_modal_module_content--aef1e.bp_modal_module_mediumSizeModal--aef1e{
3622
+ max-width:540px;
3623
+ }
3624
+ .bp_modal_module_content--aef1e.bp_modal_module_largeSizeModal--aef1e{
3625
+ max-width:620px;
3626
+ }
3627
+ .bp_modal_module_content--aef1e.bp_modal_module_xlargeSizeModal--aef1e{
3628
+ max-width:768px;
3617
3629
  }
3618
3630
  }
3619
3631
 
3620
- .bp_modal_module_content--925a9 .bp_modal_module_close--925a9{
3632
+ .bp_modal_module_content--aef1e .bp_modal_module_close--aef1e{
3621
3633
  color:var(--gray-65);
3622
3634
  position:absolute;
3623
3635
  right:var(--space-4);
3624
3636
  top:var(--space-4);
3625
3637
  }
3626
3638
 
3627
- .bp_modal_module_close--925a9.bp_modal_module_onColor--925a9{
3639
+ .bp_modal_module_close--aef1e.bp_modal_module_onColor--aef1e{
3628
3640
  background-color:var(--surface-cta-surface-tertiary);
3629
3641
  }
3630
- .bp_modal_module_close--925a9.bp_modal_module_onColor--925a9:hover{
3642
+ .bp_modal_module_close--aef1e.bp_modal_module_onColor--aef1e:hover{
3631
3643
  background-color:var(--surface-cta-surface-icon-hover);
3632
3644
  }
3633
- .bp_modal_module_close--925a9.bp_modal_module_onColor--925a9:active{
3645
+ .bp_modal_module_close--aef1e.bp_modal_module_onColor--aef1e:active{
3634
3646
  background-color:var(--surface-cta-surface-icon-pressed);
3635
3647
  }
3636
3648
 
3637
- .bp_modal_module_content--925a9 .bp_modal_module_backButton--925a9{
3649
+ .bp_modal_module_content--aef1e .bp_modal_module_backButton--aef1e{
3638
3650
  color:var(--gray-65);
3639
3651
  margin-block-start:var(--space-4);
3640
3652
  margin-inline-start:var(--space-4);
3641
3653
  }
3642
- @media (min-width: 460px){
3643
- .bp_modal_module_content--925a9 .bp_modal_module_backButton--925a9{
3654
+ @media (width > 459px){
3655
+ .bp_modal_module_content--aef1e .bp_modal_module_backButton--aef1e{
3644
3656
  height:var(--size-10);
3645
3657
  width:var(--size-10);
3646
3658
  }
3647
3659
  }
3648
3660
 
3649
- .bp_modal_module_modalHeader--925a9{
3661
+ .bp_modal_module_modalHeader--aef1e{
3650
3662
  display:flex;
3651
3663
  }
3652
3664
 
3653
- .bp_modal_module_modalTitle--925a9{
3665
+ .bp_modal_module_modalTitle--aef1e{
3654
3666
  display:flex;
3655
3667
  flex-direction:column;
3656
3668
  gap:var(--space-2);
3657
3669
  padding:var(--space-5) var(--space-12) var(--space-5) var(--space-4);
3658
3670
  }
3659
- @media (min-width: 460px){
3660
- .bp_modal_module_modalTitle--925a9{
3671
+ @media (width > 459px){
3672
+ .bp_modal_module_modalTitle--aef1e{
3661
3673
  padding:var(--space-6) var(--space-16) var(--space-6) var(--space-6);
3662
3674
  }
3663
3675
  }
3664
3676
 
3665
- .bp_modal_module_body--925a9{
3677
+ .bp_modal_module_body--aef1e{
3666
3678
  padding:var(--space-6) var(--space-4) var(--space-4);
3667
3679
  }
3668
- @media (min-width: 460px){
3669
- .bp_modal_module_body--925a9{
3680
+ @media (width > 459px){
3681
+ .bp_modal_module_body--aef1e{
3670
3682
  padding:var(--space-6) var(--space-6) var(--space-4);
3671
3683
  }
3672
3684
  }
3673
3685
 
3674
- .bp_modal_module_scrollableContainer--925a9{
3686
+ .bp_modal_module_scrollableContainer--aef1e{
3675
3687
  flex-grow:1;
3676
3688
  overflow-y:auto;
3677
3689
  }
3678
3690
 
3679
- .bp_modal_module_headerDividerLine--925a9{
3691
+ .bp_modal_module_headerDividerLine--aef1e{
3680
3692
  position:relative;
3681
3693
  }
3682
- .bp_modal_module_headerDividerLine--925a9::after{
3694
+ .bp_modal_module_headerDividerLine--aef1e::after{
3683
3695
  border-bottom:var(--border-1) solid var(--border-divider-border);
3684
3696
  bottom:0;
3685
3697
  content:"";
@@ -3687,17 +3699,17 @@ table.bp_inline_table_module_inlineTable--b023b tr:not(:last-child) td{
3687
3699
  position:absolute;
3688
3700
  right:var(--space-4);
3689
3701
  }
3690
- @media (min-width: 460px){
3691
- .bp_modal_module_headerDividerLine--925a9::after{
3702
+ @media (width > 459px){
3703
+ .bp_modal_module_headerDividerLine--aef1e::after{
3692
3704
  left:var(--space-6);
3693
3705
  right:var(--space-6);
3694
3706
  }
3695
3707
  }
3696
3708
 
3697
- .bp_modal_module_footerDividerLine--925a9{
3709
+ .bp_modal_module_footerDividerLine--aef1e{
3698
3710
  position:relative;
3699
3711
  }
3700
- .bp_modal_module_footerDividerLine--925a9::before{
3712
+ .bp_modal_module_footerDividerLine--aef1e::before{
3701
3713
  border-bottom:var(--border-1) solid var(--border-divider-border);
3702
3714
  content:"";
3703
3715
  left:var(--space-4);
@@ -3705,29 +3717,29 @@ table.bp_inline_table_module_inlineTable--b023b tr:not(:last-child) td{
3705
3717
  right:var(--space-4);
3706
3718
  top:0;
3707
3719
  }
3708
- @media (min-width: 460px){
3709
- .bp_modal_module_footerDividerLine--925a9::before{
3720
+ @media (width > 459px){
3721
+ .bp_modal_module_footerDividerLine--aef1e::before{
3710
3722
  left:var(--space-6);
3711
3723
  right:var(--space-6);
3712
3724
  }
3713
3725
  }
3714
3726
 
3715
- .bp_modal_module_footer--925a9{
3727
+ .bp_modal_module_footer--aef1e{
3716
3728
  display:flex;
3717
3729
  justify-content:flex-end;
3718
3730
  padding:var(--space-4);
3719
3731
  }
3720
- @media (min-width: 460px){
3721
- .bp_modal_module_footer--925a9{
3732
+ @media (width > 459px){
3733
+ .bp_modal_module_footer--aef1e{
3722
3734
  padding:var(--space-6);
3723
3735
  }
3724
3736
  }
3725
3737
 
3726
- .bp_modal_module_footerButton--925a9 + .bp_modal_module_footerButton--925a9{
3738
+ .bp_modal_module_footerButton--aef1e + .bp_modal_module_footerButton--aef1e{
3727
3739
  margin-inline-start:var(--space-3);
3728
3740
  }
3729
3741
 
3730
- @keyframes bp_modal_module_popup_bounce_in--925a9{
3742
+ @keyframes bp_modal_module_popup_bounce_in--aef1e{
3731
3743
  0%{
3732
3744
  transform:scale3d(.1, .1, 1);
3733
3745
  }
package/lib-esm/index.js CHANGED
@@ -56,7 +56,7 @@ export { getSupplementaryFontFacesConfig } from './primitives/supplementary-font
56
56
  export { Tabs } from './primitives/tabs/index.js';
57
57
  export { Radio } from './radio-group/index.js';
58
58
  export { SearchInput } from './search-input/index.js';
59
- export { Select } from './select/select.js';
59
+ export { SELECT_EMPTY_VALUE, Select } from './select/select.js';
60
60
  export { SidePanel } from './side-panel/side-panel.js';
61
61
  export { Slider } from './slider/slider.js';
62
62
  export { Status } from './status/status.js';
@@ -4,6 +4,10 @@ export interface InputChipProps extends HTMLAttributes<HTMLElement> {
4
4
  * Text content inside the Chip.
5
5
  * */
6
6
  label: string;
7
+ /**
8
+ * Custom tooltip for the Chip.
9
+ */
10
+ tooltip?: string;
7
11
  /**
8
12
  * The Avatar element to display.
9
13
  */
@@ -20,7 +20,7 @@ const ModalClose = /*#__PURE__*/forwardRef(({
20
20
  }, forwardedRef) => {
21
21
  // Change IconButton size for Mobile (only when IconButton size is large)
22
22
  // TODO: change to media query tokens
23
- const breakpoint = 460;
23
+ const breakpoint = 459;
24
24
  const isMobile = useMedia(`(max-width: ${breakpoint}px)`);
25
25
  let iconButtonSize = size;
26
26
  if (size === 'large' && isMobile) {
@@ -3,4 +3,6 @@ import * as RadixDialog from '@radix-ui/react-dialog';
3
3
  /**
4
4
  * Contains content to be rendered in the open modal.
5
5
  */
6
- export declare const ModalContent: import("react").ForwardRefExoticComponent<RadixDialog.DialogContentProps & Pick<RadixDialog.DialogPortalProps, "container"> & import("react").RefAttributes<HTMLDivElement>>;
6
+ export declare const ModalContent: import("react").ForwardRefExoticComponent<RadixDialog.DialogContentProps & Pick<RadixDialog.DialogPortalProps, "container"> & {
7
+ size: "small" | "medium" | "large" | "xlarge";
8
+ } & import("react").RefAttributes<HTMLDivElement>>;
@@ -12,6 +12,7 @@ const ModalContent = /*#__PURE__*/forwardRef(({
12
12
  children,
13
13
  container,
14
14
  className,
15
+ size,
15
16
  ...props
16
17
  }, forwardedRef) => jsx(RadixDialog.Portal, {
17
18
  container: container,
@@ -21,7 +22,7 @@ const ModalContent = /*#__PURE__*/forwardRef(({
21
22
  ...props,
22
23
  ref: forwardedRef,
23
24
  asChild: asChild,
24
- className: clsx(styles.content, className),
25
+ className: clsx(styles.content, styles[`${size}SizeModal`], className),
25
26
  children: children
26
27
  })
27
28
  })
@@ -10,7 +10,7 @@ import { type ModalProps } from './types';
10
10
  <Modal.Trigger>
11
11
  <button type="button">Trigger</button>
12
12
  </Modal.Trigger>
13
- <Modal.Content>
13
+ <Modal.Content size="small">
14
14
  <Modal.Header>My Title</Modal.Header>
15
15
  <Modal.ScrollableContainer>
16
16
  <Modal.Body>Content of my modal</Modal.Body>
@@ -26,7 +26,9 @@ import { type ModalProps } from './types';
26
26
  export declare const Modal: (({ children, modal, ...props }: ModalProps) => JSX.Element) & {
27
27
  Body: import("react").ForwardRefExoticComponent<import("./types").ModalBodyProps & import("react").RefAttributes<HTMLDivElement>>;
28
28
  Close: import("react").ForwardRefExoticComponent<import("./types").ModalCloseProps & import("react").RefAttributes<HTMLButtonElement>>;
29
- Content: import("react").ForwardRefExoticComponent<import("@radix-ui/react-dialog").DialogContentProps & Pick<import("@radix-ui/react-dialog").DialogPortalProps, "container"> & import("react").RefAttributes<HTMLDivElement>>;
29
+ Content: import("react").ForwardRefExoticComponent<import("@radix-ui/react-dialog").DialogContentProps & Pick<import("@radix-ui/react-dialog").DialogPortalProps, "container"> & {
30
+ size: "small" | "large" | "medium" | "xlarge";
31
+ } & import("react").RefAttributes<HTMLDivElement>>;
30
32
  Footer: import("react").ForwardRefExoticComponent<import("./types").ModalFooterProps & import("react").RefAttributes<HTMLDivElement>> & {
31
33
  PrimaryButton: import("react").ForwardRefExoticComponent<(Omit<import("../primitives/base-button").BaseButtonInterface & Required<Pick<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
32
34
  children?: string | string[] | undefined;
@@ -31,7 +31,7 @@ const Root = ({
31
31
  <Modal.Trigger>
32
32
  <button type="button">Trigger</button>
33
33
  </Modal.Trigger>
34
- <Modal.Content>
34
+ <Modal.Content size="small">
35
35
  <Modal.Header>My Title</Modal.Header>
36
36
  <Modal.ScrollableContainer>
37
37
  <Modal.Body>Content of my modal</Modal.Body>
@@ -1,4 +1,4 @@
1
1
  import '../index.css';
2
- var styles = {"overlay":"bp_modal_module_overlay--925a9","content":"bp_modal_module_content--925a9","popup_bounce_in":"bp_modal_module_popup_bounce_in--925a9","close":"bp_modal_module_close--925a9","onColor":"bp_modal_module_onColor--925a9","backButton":"bp_modal_module_backButton--925a9","modalHeader":"bp_modal_module_modalHeader--925a9","modalTitle":"bp_modal_module_modalTitle--925a9","body":"bp_modal_module_body--925a9","scrollableContainer":"bp_modal_module_scrollableContainer--925a9","headerDividerLine":"bp_modal_module_headerDividerLine--925a9","footerDividerLine":"bp_modal_module_footerDividerLine--925a9","footer":"bp_modal_module_footer--925a9","footerButton":"bp_modal_module_footerButton--925a9"};
2
+ var styles = {"overlay":"bp_modal_module_overlay--aef1e","content":"bp_modal_module_content--aef1e","popup_bounce_in":"bp_modal_module_popup_bounce_in--aef1e","smallSizeModal":"bp_modal_module_smallSizeModal--aef1e","mediumSizeModal":"bp_modal_module_mediumSizeModal--aef1e","largeSizeModal":"bp_modal_module_largeSizeModal--aef1e","xlargeSizeModal":"bp_modal_module_xlargeSizeModal--aef1e","close":"bp_modal_module_close--aef1e","onColor":"bp_modal_module_onColor--aef1e","backButton":"bp_modal_module_backButton--aef1e","modalHeader":"bp_modal_module_modalHeader--aef1e","modalTitle":"bp_modal_module_modalTitle--aef1e","body":"bp_modal_module_body--aef1e","scrollableContainer":"bp_modal_module_scrollableContainer--aef1e","headerDividerLine":"bp_modal_module_headerDividerLine--aef1e","footerDividerLine":"bp_modal_module_footerDividerLine--aef1e","footer":"bp_modal_module_footer--aef1e","footerButton":"bp_modal_module_footerButton--aef1e"};
3
3
 
4
4
  export { styles as default };
@@ -2,7 +2,14 @@ import { type DialogContentProps, type DialogPortalProps, type DialogProps, type
2
2
  import { type FunctionComponent, type HTMLAttributes, type PropsWithChildren, type ReactElement, type ReactNode, type SVGProps } from 'react';
3
3
  import { type IconButtonProps } from '../primitives/icon-button';
4
4
  export type ModalProps = DialogProps;
5
- export type ModalContentProps = DialogContentProps & Pick<DialogPortalProps, 'container'>;
5
+ export type ModalContentProps = DialogContentProps & Pick<DialogPortalProps, 'container'> & {
6
+ /** The size of the modal content.
7
+ * small: max-width: 460px
8
+ * medium: max-width: 540px
9
+ * large: max-width: 620px
10
+ * xlarge: max-width: 768px */
11
+ size: 'small' | 'medium' | 'large' | 'xlarge';
12
+ };
6
13
  export interface ModalCloseProps {
7
14
  /** The aria-label for the Close element */
8
15
  'aria-label': string;
@@ -1,2 +1,2 @@
1
- export { Select } from './select';
1
+ export { SELECT_EMPTY_VALUE, Select } from './select';
2
2
  export { type SelectOptionProps, type SelectProps } from './types';
@@ -34,3 +34,10 @@ export declare const Select: import("react").ForwardRefExoticComponent<Omit<Sele
34
34
  */
35
35
  Separator: import("react").ForwardRefExoticComponent<import("react").RefAttributes<HTMLHRElement>>;
36
36
  };
37
+ /**
38
+ * This can be used as a symbol to set a value for an option that serves as a placeholder.
39
+ * With additional handling added to onValueChange, it can be used to clear the value.
40
+ *
41
+ * See: https://github.com/radix-ui/primitives/issues/2706 for more details.
42
+ */
43
+ export declare const SELECT_EMPTY_VALUE = "__empty__";
@@ -183,5 +183,12 @@ const Select = Object.assign(Root, {
183
183
  */
184
184
  Separator
185
185
  });
186
+ /**
187
+ * This can be used as a symbol to set a value for an option that serves as a placeholder.
188
+ * With additional handling added to onValueChange, it can be used to clear the value.
189
+ *
190
+ * See: https://github.com/radix-ui/primitives/issues/2706 for more details.
191
+ */
192
+ const SELECT_EMPTY_VALUE = '__empty__';
186
193
 
187
- export { Select };
194
+ export { SELECT_EMPTY_VALUE, Select };
@@ -0,0 +1,22 @@
1
+ export interface ControlledInputValueProps<ValueType, ChangedValueType = ValueType> {
2
+ defaultValue?: never;
3
+ onChange?: (value: ChangedValueType | null) => void;
4
+ value: ValueType | null;
5
+ }
6
+ export interface UncontrolledInputValueProps<ValueType, ChangedValueType = ValueType> {
7
+ defaultValue?: ValueType | null;
8
+ onChange?: (value: ChangedValueType | null) => void;
9
+ value?: never;
10
+ }
11
+ /**
12
+ * Represents the props for an input's value.
13
+ * It is a generic type that should be used for inputs that can be used as either controlled or uncontrolled.
14
+ *
15
+ * @template ValueType - The type of the value.
16
+ * @template ChangedValueType - The type of the changed value. By default, it is the same as ValueType.
17
+ *
18
+ * @property {ValueType | null} defaultValue - The default value of the uncontrolled input. Optional. Use `null` to signify no value.
19
+ * @property {(value: ChangedValueType | null) => void} onChange - The function to be called when the value changes. It is optional.
20
+ * @property {ValueType | null} value - The current value of the controlled input. Use `null` to signify no value. If both `value` and `defaultValue` are provided, `value` will be used.
21
+ */
22
+ export type InputValueProps<ValueType, ChangedValueType = ValueType> = UncontrolledInputValueProps<ValueType, ChangedValueType> | ControlledInputValueProps<ValueType, ChangedValueType>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@box/blueprint-web",
3
- "version": "6.45.3",
3
+ "version": "7.0.1",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -21,43 +21,44 @@
21
21
  "**/*.scss"
22
22
  ],
23
23
  "dependencies": {
24
- "@ariakit/react": "0.4.1",
25
- "@ariakit/react-core": "0.4.1",
24
+ "@ariakit/react": "0.4.5",
25
+ "@ariakit/react-core": "0.4.5",
26
26
  "@box/blueprint-web-assets": "^4.16.0",
27
- "@internationalized/date": "^3.5.1",
27
+ "@internationalized/date": "^3.5.4",
28
28
  "@radix-ui/react-accordion": "^1.1.2",
29
29
  "@radix-ui/react-checkbox": "^1.0.4",
30
30
  "@radix-ui/react-collapsible": "^1.0.3",
31
- "@radix-ui/react-context-menu": "2.1.4",
32
- "@radix-ui/react-dialog": "1.0.4",
33
- "@radix-ui/react-dropdown-menu": "2.0.5",
31
+ "@radix-ui/react-context-menu": "^2.1.5",
32
+ "@radix-ui/react-dialog": "^1.0.5",
33
+ "@radix-ui/react-dropdown-menu": "^2.0.6",
34
34
  "@radix-ui/react-label": "^2.0.2",
35
- "@radix-ui/react-popover": "1.0.6",
35
+ "@radix-ui/react-popover": "^1.0.7",
36
36
  "@radix-ui/react-radio-group": "^1.1.3",
37
- "@radix-ui/react-scroll-area": "^1.0.4",
38
- "@radix-ui/react-select": "1.2.2",
37
+ "@radix-ui/react-scroll-area": "^1.0.5",
38
+ "@radix-ui/react-select": "^2.0.0",
39
39
  "@radix-ui/react-slider": "^1.1.2",
40
40
  "@radix-ui/react-switch": "^1.0.3",
41
- "@radix-ui/react-toast": "1.1.4",
41
+ "@radix-ui/react-toast": "^1.1.5",
42
42
  "@radix-ui/react-toggle-group": "^1.0.4",
43
43
  "@radix-ui/react-toolbar": "^1.0.4",
44
- "@radix-ui/react-tooltip": "1.0.6",
44
+ "@radix-ui/react-tooltip": "^1.0.7",
45
45
  "@radix-ui/react-visually-hidden": "^1.0.3",
46
- "@react-aria/i18n": "^3.10.0",
47
- "@react-aria/utils": "^3.23.0",
48
- "@react-types/shared": "^3.22.0",
46
+ "@react-aria/i18n": "^3.11.1",
47
+ "@react-aria/utils": "^3.24.1",
48
+ "@react-types/shared": "^3.23.1",
49
49
  "clsx": "^1.2.1",
50
50
  "color": "2.0.1",
51
51
  "lodash": "^4.17.15",
52
- "react-aria": "^3.31.1",
53
- "react-aria-components": "1.0.1",
52
+ "react-aria": "^3.33.1",
53
+ "react-aria-components": "^1.2.1",
54
54
  "tabbable": "^4.0.0",
55
55
  "type-fest": "^3.2.0"
56
56
  },
57
57
  "devDependencies": {
58
- "@box/storybook-utils": "^0.1.0"
58
+ "@box/storybook-utils": "^0.1.0",
59
+ "react-stately": "^3.31.1"
59
60
  },
60
- "gitHead": "81fa895e9b66968d8df23731eec8dd30dca5da53",
61
+ "gitHead": "5bb69c3c599276bf63d8b23de555782344294ad0",
61
62
  "module": "lib-esm/index.js",
62
63
  "main": "lib-esm/index.js",
63
64
  "exports": {
@@ -1,8 +0,0 @@
1
- /**
2
- * @deprecated This hook is deprecated. Consider using useBreakpoint instead.
3
- * @todo Remove it in next breaking change.
4
- */
5
- export declare const useScreenSize: () => {
6
- width: number;
7
- height: number;
8
- };