@carbon/react 1.91.0 → 1.92.0-rc.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/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +951 -976
- package/es/components/Accordion/AccordionItem.d.ts +12 -1
- package/es/components/Accordion/AccordionItem.js +9 -2
- package/es/components/Breadcrumb/BreadcrumbItem.js +1 -1
- package/es/components/Checkbox/Checkbox.js +2 -2
- package/es/components/ComboBox/ComboBox.js +39 -23
- package/es/components/ComboButton/index.js +1 -1
- package/es/components/ComposedModal/ComposedModal.js +66 -17
- package/es/components/ComposedModal/ComposedModalPresence.d.ts +34 -0
- package/es/components/ComposedModal/ComposedModalPresence.js +42 -0
- package/es/components/ComposedModal/index.d.ts +1 -0
- package/es/components/ComposedModal/useComposedModalState.d.ts +7 -0
- package/es/components/ComposedModal/useComposedModalState.js +24 -0
- package/es/components/DataTable/TableBatchActions.js +2 -2
- package/es/components/DatePickerInput/DatePickerInput.js +2 -2
- package/es/components/Dialog/Dialog.js +2 -2
- package/es/components/Dropdown/Dropdown.js +5 -5
- package/es/components/ExpandableSearch/ExpandableSearch.d.ts +1 -1
- package/es/components/ExpandableSearch/ExpandableSearch.js +1 -1
- package/es/components/FeatureFlags/index.d.ts +2 -1
- package/es/components/FeatureFlags/index.js +3 -1
- package/es/components/FileUploader/FileUploader.js +2 -2
- package/es/components/FileUploader/FileUploaderItem.js +2 -2
- package/es/components/FluidTextInput/FluidPasswordInput.js +24 -5
- package/es/components/FluidTextInput/index.js +1 -1
- package/es/components/FormLabel/FormLabel.js +1 -1
- package/es/components/ListBox/ListBox.d.ts +1 -1
- package/es/components/ListBox/ListBox.js +1 -2
- package/es/components/ListItem/ListItem.js +1 -1
- package/es/components/Menu/MenuItem.js +2 -2
- package/es/components/MenuButton/index.d.ts +1 -1
- package/es/components/MenuButton/index.js +1 -1
- package/es/components/Modal/Modal.js +60 -10
- package/es/components/Modal/ModalPresence.d.ts +32 -0
- package/es/components/Modal/ModalPresence.js +37 -0
- package/es/components/Modal/index.d.ts +2 -1
- package/es/components/Modal/index.js +1 -0
- package/es/components/MultiSelect/FilterableMultiSelect.js +3 -3
- package/es/components/MultiSelect/MultiSelect.js +6 -5
- package/es/components/Notification/Notification.js +2 -2
- package/es/components/NumberInput/NumberInput.d.ts +21 -11
- package/es/components/NumberInput/NumberInput.js +40 -26
- package/es/components/OverflowMenu/OverflowMenu.js +2 -3
- package/es/components/OverflowMenu/next/index.js +1 -1
- package/es/components/OverflowMenuItem/OverflowMenuItem.js +1 -1
- package/es/components/PageHeader/PageHeader.js +2 -2
- package/es/components/ProgressIndicator/ProgressIndicator.js +1 -1
- package/es/components/RadioButton/RadioButton.js +3 -3
- package/es/components/RadioButtonGroup/RadioButtonGroup.js +2 -2
- package/es/components/RadioTile/RadioTile.js +2 -2
- package/es/components/Select/Select.js +2 -2
- package/es/components/Slider/Slider.js +2 -2
- package/es/components/StructuredList/StructuredList.js +2 -2
- package/es/components/Tabs/Tabs.js +2 -2
- package/es/components/Tag/DismissibleTag.js +3 -3
- package/es/components/Tag/OperationalTag.js +3 -3
- package/es/components/Tag/SelectableTag.js +3 -3
- package/es/components/Tag/Tag.js +2 -2
- package/es/components/Text/Text.d.ts +1 -1
- package/es/components/Text/Text.js +0 -1
- package/es/components/Text/TextDirection.d.ts +1 -1
- package/es/components/Text/TextDirection.js +0 -1
- package/es/components/Text/createTextComponent.d.ts +2 -8
- package/es/components/Text/createTextComponent.js +2 -2
- package/es/components/Text/index.d.ts +0 -8
- package/es/components/TextArea/TextArea.js +2 -2
- package/es/components/TextInput/TextInput.js +2 -2
- package/es/components/Tile/Tile.js +2 -2
- package/es/components/Toggle/Toggle.js +2 -2
- package/es/components/UIShell/Switcher.js +0 -26
- package/es/index.d.ts +1 -1
- package/es/index.js +6 -4
- package/es/internal/useNormalizedInputProps.js +2 -2
- package/es/internal/usePresence.d.ts +17 -0
- package/es/internal/usePresence.js +66 -0
- package/es/internal/usePresenceContext.d.ts +25 -0
- package/es/internal/usePresenceContext.js +46 -0
- package/es/tools/mergeRefs.d.ts +5 -5
- package/es/tools/mergeRefs.js +16 -12
- package/lib/components/Accordion/AccordionItem.d.ts +12 -1
- package/lib/components/Accordion/AccordionItem.js +9 -2
- package/lib/components/Breadcrumb/BreadcrumbItem.js +1 -1
- package/lib/components/Checkbox/Checkbox.js +2 -2
- package/lib/components/ComboBox/ComboBox.js +39 -23
- package/lib/components/ComboButton/index.js +1 -1
- package/lib/components/ComposedModal/ComposedModal.js +65 -16
- package/lib/components/ComposedModal/ComposedModalPresence.d.ts +34 -0
- package/lib/components/ComposedModal/ComposedModalPresence.js +46 -0
- package/lib/components/ComposedModal/index.d.ts +1 -0
- package/lib/components/ComposedModal/useComposedModalState.d.ts +7 -0
- package/lib/components/ComposedModal/useComposedModalState.js +26 -0
- package/lib/components/DataTable/TableBatchActions.js +2 -2
- package/lib/components/DatePickerInput/DatePickerInput.js +2 -2
- package/lib/components/Dialog/Dialog.js +2 -2
- package/lib/components/Dropdown/Dropdown.js +3 -3
- package/lib/components/ExpandableSearch/ExpandableSearch.d.ts +1 -1
- package/lib/components/ExpandableSearch/ExpandableSearch.js +1 -1
- package/lib/components/FeatureFlags/index.d.ts +2 -1
- package/lib/components/FeatureFlags/index.js +3 -1
- package/lib/components/FileUploader/FileUploader.js +2 -2
- package/lib/components/FileUploader/FileUploaderItem.js +2 -2
- package/lib/components/FluidTextInput/FluidPasswordInput.js +26 -5
- package/lib/components/FluidTextInput/index.js +2 -1
- package/lib/components/FormLabel/FormLabel.js +1 -1
- package/lib/components/ListBox/ListBox.d.ts +1 -1
- package/lib/components/ListBox/ListBox.js +1 -2
- package/lib/components/ListItem/ListItem.js +1 -1
- package/lib/components/Menu/MenuItem.js +2 -2
- package/lib/components/MenuButton/index.d.ts +1 -1
- package/lib/components/MenuButton/index.js +1 -1
- package/lib/components/Modal/Modal.js +59 -9
- package/lib/components/Modal/ModalPresence.d.ts +32 -0
- package/lib/components/Modal/ModalPresence.js +41 -0
- package/lib/components/Modal/index.d.ts +2 -1
- package/lib/components/Modal/index.js +1 -0
- package/lib/components/MultiSelect/FilterableMultiSelect.js +3 -3
- package/lib/components/MultiSelect/MultiSelect.js +4 -3
- package/lib/components/Notification/Notification.js +2 -2
- package/lib/components/NumberInput/NumberInput.d.ts +21 -11
- package/lib/components/NumberInput/NumberInput.js +40 -26
- package/lib/components/OverflowMenu/OverflowMenu.js +2 -3
- package/lib/components/OverflowMenu/next/index.js +1 -1
- package/lib/components/OverflowMenuItem/OverflowMenuItem.js +1 -1
- package/lib/components/PageHeader/PageHeader.js +2 -2
- package/lib/components/ProgressIndicator/ProgressIndicator.js +1 -1
- package/lib/components/RadioButton/RadioButton.js +3 -3
- package/lib/components/RadioButtonGroup/RadioButtonGroup.js +3 -3
- package/lib/components/RadioTile/RadioTile.js +2 -2
- package/lib/components/Select/Select.js +2 -2
- package/lib/components/Slider/Slider.js +2 -2
- package/lib/components/StructuredList/StructuredList.js +2 -2
- package/lib/components/Tabs/Tabs.js +2 -2
- package/lib/components/Tag/DismissibleTag.js +3 -3
- package/lib/components/Tag/OperationalTag.js +3 -3
- package/lib/components/Tag/SelectableTag.js +3 -3
- package/lib/components/Tag/Tag.js +2 -2
- package/lib/components/Text/Text.d.ts +1 -1
- package/lib/components/Text/Text.js +0 -1
- package/lib/components/Text/TextDirection.d.ts +1 -1
- package/lib/components/Text/TextDirection.js +0 -1
- package/lib/components/Text/createTextComponent.d.ts +2 -8
- package/lib/components/Text/createTextComponent.js +2 -2
- package/lib/components/Text/index.d.ts +0 -8
- package/lib/components/TextArea/TextArea.js +2 -2
- package/lib/components/TextInput/TextInput.js +2 -2
- package/lib/components/Tile/Tile.js +2 -2
- package/lib/components/Toggle/Toggle.js +2 -2
- package/lib/components/UIShell/Switcher.js +0 -26
- package/lib/index.d.ts +1 -1
- package/lib/index.js +13 -8
- package/lib/internal/useNormalizedInputProps.js +2 -2
- package/lib/internal/usePresence.d.ts +17 -0
- package/lib/internal/usePresence.js +68 -0
- package/lib/internal/usePresenceContext.d.ts +25 -0
- package/lib/internal/usePresenceContext.js +48 -0
- package/lib/tools/mergeRefs.d.ts +5 -5
- package/lib/tools/mergeRefs.js +16 -14
- package/package.json +7 -7
- package/telemetry.yml +4 -0
- package/es/components/Text/index.js +0 -16
- package/lib/components/Text/index.js +0 -20
|
@@ -12,6 +12,11 @@ export interface AccordionItemProps {
|
|
|
12
12
|
* this value will be managed by the parent Accordion.
|
|
13
13
|
*/
|
|
14
14
|
disabled?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Specify a custom label for the accordion button.
|
|
17
|
+
* This is important for accessibility when the accordion has no visible title.
|
|
18
|
+
*/
|
|
19
|
+
'aria-label'?: AriaAttributes['aria-label'];
|
|
15
20
|
/**
|
|
16
21
|
* The handler of the massaged `click` event.
|
|
17
22
|
*/
|
|
@@ -52,6 +57,7 @@ export interface AccordionItemProps {
|
|
|
52
57
|
export interface AccordionToggleProps {
|
|
53
58
|
'aria-controls'?: AriaAttributes['aria-controls'];
|
|
54
59
|
'aria-expanded'?: AriaAttributes['aria-expanded'];
|
|
60
|
+
'aria-label'?: AriaAttributes['aria-label'];
|
|
55
61
|
className?: string;
|
|
56
62
|
disabled?: boolean;
|
|
57
63
|
onClick?: MouseEventHandler<HTMLButtonElement>;
|
|
@@ -59,7 +65,7 @@ export interface AccordionToggleProps {
|
|
|
59
65
|
type?: 'button';
|
|
60
66
|
}
|
|
61
67
|
declare function AccordionItem({ children, className: customClassName, open, onHeadingClick, renderExpando, // remove renderExpando in next major release
|
|
62
|
-
renderToggle, title, disabled: controlledDisabled, handleAnimationEnd, ...rest }: PropsWithChildren<AccordionItemProps>): import("react/jsx-runtime").JSX.Element;
|
|
68
|
+
renderToggle, title, disabled: controlledDisabled, handleAnimationEnd, 'aria-label': ariaLabel, ...rest }: PropsWithChildren<AccordionItemProps>): import("react/jsx-runtime").JSX.Element;
|
|
63
69
|
declare namespace AccordionItem {
|
|
64
70
|
var propTypes: {
|
|
65
71
|
/**
|
|
@@ -74,6 +80,11 @@ declare namespace AccordionItem {
|
|
|
74
80
|
* Specify whether an individual AccordionItem should be disabled
|
|
75
81
|
*/
|
|
76
82
|
disabled: PropTypes.Requireable<boolean>;
|
|
83
|
+
/**
|
|
84
|
+
* Specify a custom label for the accordion button.
|
|
85
|
+
* This is important for accessibility when the accordion has no visible title.
|
|
86
|
+
*/
|
|
87
|
+
'aria-label': PropTypes.Requireable<string>;
|
|
77
88
|
/**
|
|
78
89
|
* The handler of the massaged `click` event.
|
|
79
90
|
*/
|
|
@@ -10,14 +10,14 @@ import { ChevronRight } from '@carbon/icons-react';
|
|
|
10
10
|
import cx from 'classnames';
|
|
11
11
|
import PropTypes from 'prop-types';
|
|
12
12
|
import React, { useState, useContext } from 'react';
|
|
13
|
-
import '../Text/
|
|
13
|
+
import { Text } from '../Text/Text.js';
|
|
14
|
+
import '../Text/TextDirection.js';
|
|
14
15
|
import { Escape } from '../../internal/keyboard/keys.js';
|
|
15
16
|
import { match } from '../../internal/keyboard/match.js';
|
|
16
17
|
import { useId } from '../../internal/useId.js';
|
|
17
18
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
18
19
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
19
20
|
import { AccordionContext } from './AccordionProvider.js';
|
|
20
|
-
import { Text } from '../Text/Text.js';
|
|
21
21
|
|
|
22
22
|
const defaultRenderToggle = props => /*#__PURE__*/React.createElement("button", _extends({
|
|
23
23
|
type: "button"
|
|
@@ -33,6 +33,7 @@ function AccordionItem({
|
|
|
33
33
|
title = 'title',
|
|
34
34
|
disabled: controlledDisabled,
|
|
35
35
|
handleAnimationEnd,
|
|
36
|
+
'aria-label': ariaLabel,
|
|
36
37
|
...rest
|
|
37
38
|
}) {
|
|
38
39
|
const [isOpen, setIsOpen] = useState(open);
|
|
@@ -96,6 +97,7 @@ function AccordionItem({
|
|
|
96
97
|
disabled: disabled,
|
|
97
98
|
"aria-controls": id,
|
|
98
99
|
"aria-expanded": isOpen,
|
|
100
|
+
"aria-label": ariaLabel,
|
|
99
101
|
className: `${prefix}--accordion__heading`,
|
|
100
102
|
onClick: onClick,
|
|
101
103
|
onKeyDown: onKeyDown,
|
|
@@ -127,6 +129,11 @@ AccordionItem.propTypes = {
|
|
|
127
129
|
* Specify whether an individual AccordionItem should be disabled
|
|
128
130
|
*/
|
|
129
131
|
disabled: PropTypes.bool,
|
|
132
|
+
/**
|
|
133
|
+
* Specify a custom label for the accordion button.
|
|
134
|
+
* This is important for accessibility when the accordion has no visible title.
|
|
135
|
+
*/
|
|
136
|
+
'aria-label': PropTypes.string,
|
|
130
137
|
/**
|
|
131
138
|
* The handler of the massaged `click` event.
|
|
132
139
|
*/
|
|
@@ -12,8 +12,8 @@ import cx from 'classnames';
|
|
|
12
12
|
import Link from '../Link/Link.js';
|
|
13
13
|
import { OverflowMenuHorizontal } from '@carbon/icons-react';
|
|
14
14
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
|
-
import '../Text/index.js';
|
|
16
15
|
import { Text } from '../Text/Text.js';
|
|
16
|
+
import '../Text/TextDirection.js';
|
|
17
17
|
|
|
18
18
|
const frFn = forwardRef;
|
|
19
19
|
const BreadcrumbItem = frFn((props, ref) => {
|
|
@@ -9,7 +9,8 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
|
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
10
|
import React, { cloneElement } from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
|
-
import '../Text/
|
|
12
|
+
import { Text } from '../Text/Text.js';
|
|
13
|
+
import '../Text/TextDirection.js';
|
|
13
14
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
14
15
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
16
|
import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
|
|
@@ -17,7 +18,6 @@ import { useId } from '../../internal/useId.js';
|
|
|
17
18
|
import { noopFn } from '../../internal/noopFn.js';
|
|
18
19
|
import { AILabel } from '../AILabel/index.js';
|
|
19
20
|
import { isComponentElement } from '../../internal/utils.js';
|
|
20
|
-
import { Text } from '../Text/Text.js';
|
|
21
21
|
|
|
22
22
|
const Checkbox = /*#__PURE__*/React.forwardRef(({
|
|
23
23
|
className,
|
|
@@ -10,7 +10,8 @@ import cx from 'classnames';
|
|
|
10
10
|
import { useCombobox } from 'downshift';
|
|
11
11
|
import PropTypes from 'prop-types';
|
|
12
12
|
import React, { forwardRef, useRef, useEffect, useState, useContext, useCallback, useMemo, cloneElement } from 'react';
|
|
13
|
-
import '../Text/
|
|
13
|
+
import { Text } from '../Text/Text.js';
|
|
14
|
+
import '../Text/TextDirection.js';
|
|
14
15
|
import { WarningFilled, WarningAltFilled, Checkmark } from '@carbon/icons-react';
|
|
15
16
|
import isEqual from 'react-fast-compare';
|
|
16
17
|
import ListBox from '../ListBox/index.js';
|
|
@@ -19,7 +20,7 @@ import ListBoxTrigger from '../ListBox/next/ListBoxTrigger.js';
|
|
|
19
20
|
import { Space, Enter, Escape, Home, End } from '../../internal/keyboard/keys.js';
|
|
20
21
|
import { match } from '../../internal/keyboard/match.js';
|
|
21
22
|
import { useId } from '../../internal/useId.js';
|
|
22
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
23
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
23
24
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
24
25
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
25
26
|
import '../FluidForm/FluidForm.js';
|
|
@@ -30,7 +31,6 @@ import { AILabel } from '../AILabel/index.js';
|
|
|
30
31
|
import { defaultItemToString } from '../../internal/defaultItemToString.js';
|
|
31
32
|
import { isComponentElement } from '../../internal/utils.js';
|
|
32
33
|
import { ListBoxSizePropType } from '../ListBox/ListBoxPropTypes.js';
|
|
33
|
-
import { Text } from '../Text/Text.js';
|
|
34
34
|
|
|
35
35
|
const {
|
|
36
36
|
InputBlur,
|
|
@@ -281,9 +281,13 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
281
281
|
switch (type) {
|
|
282
282
|
case InputBlur:
|
|
283
283
|
{
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
// If custom values are allowed, treat whatever the user typed as
|
|
285
|
+
// the value.
|
|
286
|
+
if (allowCustomValue && highlightedIndex === -1) {
|
|
287
|
+
const {
|
|
288
|
+
inputValue
|
|
289
|
+
} = state;
|
|
290
|
+
changes.selectedItem = inputValue;
|
|
287
291
|
if (onChange) {
|
|
288
292
|
onChange({
|
|
289
293
|
selectedItem: inputValue,
|
|
@@ -292,17 +296,28 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
292
296
|
}
|
|
293
297
|
return changes;
|
|
294
298
|
}
|
|
295
|
-
|
|
299
|
+
|
|
300
|
+
// If a new item was selected, keep its label in the input.
|
|
301
|
+
if (state.inputValue && highlightedIndex === -1 && changes.selectedItem) {
|
|
296
302
|
return {
|
|
297
303
|
...changes,
|
|
298
304
|
inputValue: itemToString(changes.selectedItem)
|
|
299
305
|
};
|
|
300
306
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
307
|
+
|
|
308
|
+
// If custom values are not allowed, normalize any non-matching
|
|
309
|
+
// text. If the input isn’t an exact item label, restore the
|
|
310
|
+
// selected label if there is one, or clear it.
|
|
311
|
+
if (!allowCustomValue) {
|
|
312
|
+
const currentInput = state.inputValue ?? '';
|
|
313
|
+
const hasExactMatch = !!currentInput && items.some(item => itemToString(item) === currentInput);
|
|
314
|
+
if (!hasExactMatch) {
|
|
315
|
+
const restoredInput = state.selectedItem !== null ? itemToString(state.selectedItem) : '';
|
|
316
|
+
return {
|
|
317
|
+
...changes,
|
|
318
|
+
inputValue: restoredInput
|
|
319
|
+
};
|
|
320
|
+
}
|
|
306
321
|
}
|
|
307
322
|
return changes;
|
|
308
323
|
}
|
|
@@ -355,16 +370,17 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
355
370
|
};
|
|
356
371
|
case FunctionToggleMenu:
|
|
357
372
|
case ToggleButtonClick:
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
373
|
+
// When closing the menu, apply the same normalization as blur.
|
|
374
|
+
if (state.isOpen && !changes.isOpen && !allowCustomValue) {
|
|
375
|
+
const currentInput = state.inputValue ?? '';
|
|
376
|
+
const hasExactMatch = !!currentInput && items.some(item => itemToString(item) === currentInput);
|
|
377
|
+
if (!hasExactMatch) {
|
|
378
|
+
const restoredInput = state.selectedItem !== null ? itemToString(state.selectedItem) : '';
|
|
379
|
+
return {
|
|
380
|
+
...changes,
|
|
381
|
+
inputValue: restoredInput
|
|
382
|
+
};
|
|
383
|
+
}
|
|
368
384
|
}
|
|
369
385
|
return changes;
|
|
370
386
|
case MenuMouseLeave:
|
|
@@ -391,7 +407,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
391
407
|
}
|
|
392
408
|
},
|
|
393
409
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
394
|
-
[allowCustomValue, inputValue, onChange]);
|
|
410
|
+
[allowCustomValue, inputValue, itemToString, items, onChange]);
|
|
395
411
|
const handleToggleClick = isOpen => event => {
|
|
396
412
|
if (onToggleClick) {
|
|
397
413
|
onToggleClick(event);
|
|
@@ -20,7 +20,7 @@ import { useId } from '../../internal/useId.js';
|
|
|
20
20
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
21
21
|
import { flip, hide, size, useFloating, autoUpdate } from '@floating-ui/react';
|
|
22
22
|
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
23
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
23
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
24
24
|
import { deprecateValuesWithin } from '../../prop-types/deprecateValuesWithin.js';
|
|
25
25
|
import { mapPopoverAlign } from '../../tools/mapPopoverAlign.js';
|
|
26
26
|
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
-
import React, { useRef, useState, useEffect, Children, cloneElement } from 'react';
|
|
9
|
+
import React, { useRef, useState, useContext, useEffect, Children, cloneElement } from 'react';
|
|
10
10
|
import { isElement } from 'react-is';
|
|
11
11
|
import PropTypes from 'prop-types';
|
|
12
12
|
import { Layer } from '../Layer/index.js';
|
|
13
13
|
import { ModalHeader } from './ModalHeader.js';
|
|
14
14
|
import { ModalFooter } from './ModalFooter.js';
|
|
15
15
|
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
16
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
16
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
17
17
|
import cx from 'classnames';
|
|
18
18
|
import { toggleClass } from '../../tools/toggleClass.js';
|
|
19
19
|
import { requiredIfGivenPropIsTruthy } from '../../prop-types/requiredIfGivenPropIsTruthy.js';
|
|
@@ -28,6 +28,10 @@ import { Dialog } from '../Dialog/Dialog.js';
|
|
|
28
28
|
import { warning } from '../../internal/warning.js';
|
|
29
29
|
import { AILabel } from '../AILabel/index.js';
|
|
30
30
|
import { isComponentElement } from '../../internal/utils.js';
|
|
31
|
+
import { useMergeRefs } from '@floating-ui/react';
|
|
32
|
+
import { ComposedModalPresenceContext, useExclusiveComposedModalPresenceContext, ComposedModalPresence } from './ComposedModalPresence.js';
|
|
33
|
+
import { useId } from '../../internal/useId.js';
|
|
34
|
+
import { useComposedModalState } from './useComposedModalState.js';
|
|
31
35
|
import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.js';
|
|
32
36
|
|
|
33
37
|
const ModalBody = /*#__PURE__*/React.forwardRef(function ModalBody({
|
|
@@ -95,6 +99,34 @@ ModalBody.propTypes = {
|
|
|
95
99
|
hasScrollingContent: PropTypes.bool
|
|
96
100
|
};
|
|
97
101
|
const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
|
|
102
|
+
open,
|
|
103
|
+
...props
|
|
104
|
+
}, ref) {
|
|
105
|
+
const id = useId();
|
|
106
|
+
const enablePresence = useFeatureFlag('enable-presence');
|
|
107
|
+
const hasPresenceContext = Boolean(useContext(ComposedModalPresenceContext));
|
|
108
|
+
const hasPresenceOptIn = enablePresence || hasPresenceContext;
|
|
109
|
+
const exclusivePresenceContext = useExclusiveComposedModalPresenceContext(id);
|
|
110
|
+
|
|
111
|
+
// if opt in and not exclusive to a presence context, wrap with presence
|
|
112
|
+
if (hasPresenceOptIn && !exclusivePresenceContext) {
|
|
113
|
+
return /*#__PURE__*/React.createElement(ComposedModalPresence, {
|
|
114
|
+
open: open ?? false,
|
|
115
|
+
_presenceId: id
|
|
116
|
+
// do not auto enable styles for opt-in by feature flag
|
|
117
|
+
,
|
|
118
|
+
_autoEnablePresence: hasPresenceContext
|
|
119
|
+
}, /*#__PURE__*/React.createElement(ComposedModalDialog, _extends({
|
|
120
|
+
open: true,
|
|
121
|
+
ref: ref
|
|
122
|
+
}, props)));
|
|
123
|
+
}
|
|
124
|
+
return /*#__PURE__*/React.createElement(ComposedModalDialog, _extends({
|
|
125
|
+
ref: ref,
|
|
126
|
+
open: open
|
|
127
|
+
}, props));
|
|
128
|
+
});
|
|
129
|
+
const ComposedModalDialog = /*#__PURE__*/React.forwardRef(function ComposedModalDialog({
|
|
98
130
|
['aria-labelledby']: ariaLabelledBy,
|
|
99
131
|
['aria-label']: ariaLabel,
|
|
100
132
|
children,
|
|
@@ -105,7 +137,7 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
|
|
|
105
137
|
isFullWidth,
|
|
106
138
|
onClose,
|
|
107
139
|
onKeyDown,
|
|
108
|
-
open,
|
|
140
|
+
open: externalOpen,
|
|
109
141
|
preventCloseOnClickOutside,
|
|
110
142
|
selectorPrimaryFocus = '[data-modal-primary-focus]',
|
|
111
143
|
selectorsFloatingMenus,
|
|
@@ -115,27 +147,30 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
|
|
|
115
147
|
...rest
|
|
116
148
|
}, ref) {
|
|
117
149
|
const prefix = usePrefix();
|
|
118
|
-
const [isOpen, setIsOpen] = useState(!!open);
|
|
119
|
-
const [wasOpen, setWasOpen] = useState(!!open);
|
|
120
150
|
const innerModal = useRef(null);
|
|
121
151
|
const button = useRef(null);
|
|
122
152
|
const startSentinel = useRef(null);
|
|
123
153
|
const endSentinel = useRef(null);
|
|
124
154
|
const onMouseDownTarget = useRef(null);
|
|
155
|
+
const presenceContext = useContext(ComposedModalPresenceContext);
|
|
156
|
+
const mergedRefs = useMergeRefs([ref, presenceContext?.presenceRef]);
|
|
157
|
+
const enablePresence = useFeatureFlag('enable-presence') || presenceContext?.autoEnablePresence;
|
|
158
|
+
|
|
159
|
+
// always mark as open when mounted with presence
|
|
160
|
+
const open = externalOpen || enablePresence;
|
|
161
|
+
const modalState = useComposedModalState(open);
|
|
162
|
+
const [isOpen, setIsOpen] = presenceContext?.modalState ?? modalState;
|
|
125
163
|
const enableDialogElement = useFeatureFlag('enable-dialog-element');
|
|
126
164
|
const focusTrapWithoutSentinels = useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
|
|
127
165
|
process.env.NODE_ENV !== "production" ? warning(!(focusTrapWithoutSentinels && enableDialogElement), '`<Modal>` detected both `focusTrapWithoutSentinels` and ' + '`enableDialogElement` feature flags are enabled. The native dialog ' + 'element handles focus, so `enableDialogElement` must be off for ' + '`focusTrapWithoutSentinels` to have any effect.') : void 0;
|
|
128
166
|
|
|
129
|
-
//
|
|
130
|
-
// and propagate it to the document.body
|
|
167
|
+
// Propagate open/close state to the document.body
|
|
131
168
|
useEffect(() => {
|
|
132
|
-
if (!enableDialogElement
|
|
133
|
-
setIsOpen(!!open);
|
|
134
|
-
setWasOpen(!!open);
|
|
169
|
+
if (!enableDialogElement) {
|
|
135
170
|
toggleClass(document.body, `${prefix}--body--with-modal-open`, !!open);
|
|
136
171
|
}
|
|
137
172
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20071
|
|
138
|
-
}, [open,
|
|
173
|
+
}, [open, prefix]);
|
|
139
174
|
// Remove the document.body className on unmount
|
|
140
175
|
useEffect(() => {
|
|
141
176
|
if (!enableDialogElement) {
|
|
@@ -226,7 +261,8 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
|
|
|
226
261
|
}
|
|
227
262
|
}
|
|
228
263
|
const modalClass = cx(`${prefix}--modal`, {
|
|
229
|
-
'is-visible': isOpen,
|
|
264
|
+
'is-visible': enablePresence || isOpen,
|
|
265
|
+
[`${prefix}--modal--enable-presence`]: presenceContext?.autoEnablePresence,
|
|
230
266
|
[`${prefix}--modal--danger`]: danger,
|
|
231
267
|
[`${prefix}--modal--slug`]: slug,
|
|
232
268
|
[`${prefix}--modal--decorator`]: decorator
|
|
@@ -280,12 +316,23 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
|
|
|
280
316
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20071
|
|
281
317
|
}, [open]);
|
|
282
318
|
useEffect(() => {
|
|
283
|
-
if (!enableDialogElement && !open && launcherButtonRef) {
|
|
319
|
+
if (!enableDialogElement && !enablePresence && !open && launcherButtonRef) {
|
|
284
320
|
setTimeout(() => {
|
|
285
321
|
launcherButtonRef.current?.focus();
|
|
286
322
|
});
|
|
287
323
|
}
|
|
288
|
-
}, [enableDialogElement, open, launcherButtonRef]);
|
|
324
|
+
}, [enableDialogElement, enablePresence, open, launcherButtonRef]);
|
|
325
|
+
// Focus launcherButtonRef on unmount
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
const launcherButton = launcherButtonRef?.current;
|
|
328
|
+
return () => {
|
|
329
|
+
if (enablePresence && launcherButton) {
|
|
330
|
+
setTimeout(() => {
|
|
331
|
+
launcherButton.focus();
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}, [enablePresence, launcherButtonRef]);
|
|
289
336
|
useEffect(() => {
|
|
290
337
|
if (!enableDialogElement) {
|
|
291
338
|
const initialFocus = focusContainerElement => {
|
|
@@ -324,7 +371,8 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
|
|
|
324
371
|
modal: true,
|
|
325
372
|
className: containerClass,
|
|
326
373
|
"aria-label": ariaLabel ? ariaLabel : generatedAriaLabel,
|
|
327
|
-
"aria-labelledby": ariaLabelledBy
|
|
374
|
+
"aria-labelledby": ariaLabelledBy,
|
|
375
|
+
"data-exiting": presenceContext?.isExiting || undefined
|
|
328
376
|
}, /*#__PURE__*/React.createElement("div", {
|
|
329
377
|
ref: innerModal,
|
|
330
378
|
className: `${prefix}--modal-container-body`
|
|
@@ -353,13 +401,14 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
|
|
|
353
401
|
return /*#__PURE__*/React.createElement(Layer, _extends({}, rest, {
|
|
354
402
|
level: 0,
|
|
355
403
|
role: "presentation",
|
|
356
|
-
ref:
|
|
404
|
+
ref: mergedRefs,
|
|
357
405
|
"aria-hidden": !open,
|
|
358
406
|
onBlur: handleBlur,
|
|
359
407
|
onClick: composeEventHandlers([rest?.onClick, handleOnClick]),
|
|
360
408
|
onMouseDown: composeEventHandlers([rest?.onMouseDown, handleOnMouseDown]),
|
|
361
409
|
onKeyDown: handleKeyDown,
|
|
362
|
-
className: modalClass
|
|
410
|
+
className: modalClass,
|
|
411
|
+
"data-exiting": presenceContext?.isExiting || undefined
|
|
363
412
|
}), modalBody);
|
|
364
413
|
});
|
|
365
414
|
ComposedModal.propTypes = {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2025
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React, { type PropsWithChildren } from 'react';
|
|
8
|
+
import { type PresenceContext } from '../../internal/usePresenceContext';
|
|
9
|
+
import { useComposedModalState } from './useComposedModalState';
|
|
10
|
+
export interface ComposedModalPresenceProps {
|
|
11
|
+
/**
|
|
12
|
+
* Specify whether the Modal is currently open
|
|
13
|
+
*/
|
|
14
|
+
open: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Internal property for backwards compatibility. Specify whether the Modal should opt in to presence mode.
|
|
17
|
+
*/
|
|
18
|
+
_autoEnablePresence?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Internal property to predefine the presence context's id for exclusivity.
|
|
21
|
+
*/
|
|
22
|
+
_presenceId?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const ComposedModalPresence: ({ open, _presenceId: presenceId, _autoEnablePresence: autoEnablePresence, children, }: PropsWithChildren<ComposedModalPresenceProps>) => import("react/jsx-runtime").JSX.Element | null;
|
|
25
|
+
interface ComposedModalPresenceContextProps extends PresenceContext {
|
|
26
|
+
modalState: ReturnType<typeof useComposedModalState>;
|
|
27
|
+
autoEnablePresence: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare const ComposedModalPresenceContext: React.Context<ComposedModalPresenceContextProps | undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* Handles occurrences where only a single composed modal must consume a context.
|
|
32
|
+
*/
|
|
33
|
+
export declare const useExclusiveComposedModalPresenceContext: (id: string) => ComposedModalPresenceContextProps | undefined;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { createContext, useContext, useMemo } from 'react';
|
|
9
|
+
import { usePresenceContext } from '../../internal/usePresenceContext.js';
|
|
10
|
+
import { useComposedModalState } from './useComposedModalState.js';
|
|
11
|
+
|
|
12
|
+
const ComposedModalPresence = ({
|
|
13
|
+
open,
|
|
14
|
+
_presenceId: presenceId,
|
|
15
|
+
_autoEnablePresence: autoEnablePresence = true,
|
|
16
|
+
children
|
|
17
|
+
}) => {
|
|
18
|
+
// Since the modal could be used without an onClose callback, we need to be aware of the internal isOpen state
|
|
19
|
+
const modalState = useComposedModalState(open);
|
|
20
|
+
const [isOpen] = modalState;
|
|
21
|
+
const [isPresent, context] = usePresenceContext(isOpen, presenceId);
|
|
22
|
+
const presenceContextValue = useMemo(() => ({
|
|
23
|
+
modalState,
|
|
24
|
+
autoEnablePresence,
|
|
25
|
+
...context
|
|
26
|
+
}), [modalState, autoEnablePresence, context]);
|
|
27
|
+
if (!isPresent) return null;
|
|
28
|
+
return /*#__PURE__*/React.createElement(ComposedModalPresenceContext, {
|
|
29
|
+
value: presenceContextValue
|
|
30
|
+
}, children);
|
|
31
|
+
};
|
|
32
|
+
const ComposedModalPresenceContext = /*#__PURE__*/createContext(undefined);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Handles occurrences where only a single composed modal must consume a context.
|
|
36
|
+
*/
|
|
37
|
+
const useExclusiveComposedModalPresenceContext = id => {
|
|
38
|
+
const ctx = useContext(ComposedModalPresenceContext);
|
|
39
|
+
return ctx?.isPresenceExclusive(id) ? ctx : undefined;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { ComposedModalPresence, ComposedModalPresenceContext, useExclusiveComposedModalPresenceContext };
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import ComposedModal from './ComposedModal';
|
|
8
8
|
export { default as ComposedModal, type ComposedModalProps, ModalBody, type ModalBodyProps, } from './ComposedModal';
|
|
9
|
+
export { ComposedModalPresence, type ComposedModalPresenceProps, } from './ComposedModalPresence';
|
|
9
10
|
export { ModalHeader, type ModalHeaderProps } from './ModalHeader';
|
|
10
11
|
export { ModalFooter, type ModalFooterProps } from './ModalFooter';
|
|
11
12
|
export default ComposedModal;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2025
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
export declare const useComposedModalState: (open: boolean | undefined) => readonly [boolean, import("react").Dispatch<import("react").SetStateAction<boolean>>];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useState, useEffect, useMemo } from 'react';
|
|
9
|
+
|
|
10
|
+
const useComposedModalState = open => {
|
|
11
|
+
const [isOpen, setIsOpen] = useState(!!open);
|
|
12
|
+
const [wasOpen, setWasOpen] = useState(!!open);
|
|
13
|
+
|
|
14
|
+
// Keep track of modal open/close state
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
if (open !== wasOpen) {
|
|
17
|
+
setIsOpen(!!open);
|
|
18
|
+
setWasOpen(!!open);
|
|
19
|
+
}
|
|
20
|
+
}, [open, wasOpen]);
|
|
21
|
+
return useMemo(() => [isOpen, setIsOpen], [isOpen]);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export { useComposedModalState };
|
|
@@ -12,9 +12,9 @@ import React from 'react';
|
|
|
12
12
|
import Button from '../Button/Button.js';
|
|
13
13
|
import '../Button/Button.Skeleton.js';
|
|
14
14
|
import TableActionList from './TableActionList.js';
|
|
15
|
-
import '../Text/index.js';
|
|
16
|
-
import { usePrefix } from '../../internal/usePrefix.js';
|
|
17
15
|
import { Text } from '../Text/Text.js';
|
|
16
|
+
import '../Text/TextDirection.js';
|
|
17
|
+
import { usePrefix } from '../../internal/usePrefix.js';
|
|
18
18
|
|
|
19
19
|
const TableBatchActionsTranslationKeys = ['carbon.table.batch.cancel', 'carbon.table.batch.items.selected', 'carbon.table.batch.item.selected', 'carbon.table.batch.selectAll'];
|
|
20
20
|
const translationKeys = {
|
|
@@ -14,11 +14,11 @@ import { usePrefix } from '../../internal/usePrefix.js';
|
|
|
14
14
|
import '../FluidForm/FluidForm.js';
|
|
15
15
|
import { FormContext } from '../FluidForm/FormContext.js';
|
|
16
16
|
import { useId } from '../../internal/useId.js';
|
|
17
|
-
import '../Text/
|
|
17
|
+
import { Text } from '../Text/Text.js';
|
|
18
|
+
import '../Text/TextDirection.js';
|
|
18
19
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
19
20
|
import { AILabel } from '../AILabel/index.js';
|
|
20
21
|
import { isComponentElement } from '../../internal/utils.js';
|
|
21
|
-
import { Text } from '../Text/Text.js';
|
|
22
22
|
|
|
23
23
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20071
|
|
24
24
|
|
|
@@ -14,7 +14,8 @@ import cx from 'classnames';
|
|
|
14
14
|
import { Close } from '@carbon/icons-react';
|
|
15
15
|
import { IconButton } from '../IconButton/index.js';
|
|
16
16
|
import { noopFn } from '../../internal/noopFn.js';
|
|
17
|
-
import '../Text/
|
|
17
|
+
import { Text } from '../Text/Text.js';
|
|
18
|
+
import '../Text/TextDirection.js';
|
|
18
19
|
import { Layer } from '../Layer/index.js';
|
|
19
20
|
import ButtonSet from '../ButtonSet/ButtonSet.js';
|
|
20
21
|
import Button from '../Button/Button.js';
|
|
@@ -22,7 +23,6 @@ import '../Button/Button.Skeleton.js';
|
|
|
22
23
|
import { useId } from '../../internal/useId.js';
|
|
23
24
|
import InlineLoading from '../InlineLoading/InlineLoading.js';
|
|
24
25
|
import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.js';
|
|
25
|
-
import { Text } from '../Text/Text.js';
|
|
26
26
|
|
|
27
27
|
const DialogContext = /*#__PURE__*/createContext({});
|
|
28
28
|
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
-
import React, { useEffect, useContext, useCallback, useMemo, useState, isValidElement, cloneElement } from 'react';
|
|
9
|
+
import React, { useEffect, useContext, useCallback, useMemo, useState, useRef, isValidElement, cloneElement } from 'react';
|
|
10
10
|
import { useSelect } from 'downshift';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import PropTypes from 'prop-types';
|
|
13
13
|
import { WarningFilled, WarningAltFilled, Checkmark } from '@carbon/icons-react';
|
|
14
14
|
import ListBox from '../ListBox/index.js';
|
|
15
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
15
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
16
16
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
17
17
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
18
18
|
import '../FluidForm/FluidForm.js';
|
|
@@ -251,7 +251,8 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
|
|
|
251
251
|
const handleFocus = evt => {
|
|
252
252
|
setIsFocused(evt.type === 'focus' && !selectedItem ? true : false);
|
|
253
253
|
};
|
|
254
|
-
const
|
|
254
|
+
const buttonRef = useRef(null);
|
|
255
|
+
const mergedRef = mergeRefs(toggleButtonProps.ref, ref, buttonRef);
|
|
255
256
|
const [currTimer, setCurrTimer] = useState();
|
|
256
257
|
const [isTyping, setIsTyping] = useState(false);
|
|
257
258
|
const onKeyDownHandler = useCallback(evt => {
|
|
@@ -287,7 +288,7 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
|
|
|
287
288
|
// NOTE: does not prevent click
|
|
288
289
|
evt.preventDefault();
|
|
289
290
|
// focus on the element as per readonly input behavior
|
|
290
|
-
|
|
291
|
+
buttonRef.current?.focus();
|
|
291
292
|
},
|
|
292
293
|
onKeyDown: evt => {
|
|
293
294
|
const selectAccessKeys = ['ArrowDown', 'ArrowUp', ' ', 'Enter'];
|
|
@@ -302,7 +303,6 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
|
|
|
302
303
|
onKeyDown: onKeyDownHandler
|
|
303
304
|
};
|
|
304
305
|
}
|
|
305
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20071
|
|
306
306
|
}, [readOnly, onKeyDownHandler]);
|
|
307
307
|
const menuProps = useMemo(() => getMenuProps({
|
|
308
308
|
ref: enableFloatingStyles || autoAlign ? refs.setFloating : null
|
|
@@ -14,7 +14,7 @@ import { usePrefix } from '../../internal/usePrefix.js';
|
|
|
14
14
|
import { composeEventHandlers } from '../../tools/events.js';
|
|
15
15
|
import { Escape } from '../../internal/keyboard/keys.js';
|
|
16
16
|
import { match } from '../../internal/keyboard/match.js';
|
|
17
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
17
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
18
18
|
|
|
19
19
|
const ExpandableSearch = /*#__PURE__*/React.forwardRef(function ExpandableSearch({
|
|
20
20
|
onBlur,
|