@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
|
@@ -17,6 +17,7 @@ export interface FeatureFlagsProps {
|
|
|
17
17
|
enableDialogElement?: boolean;
|
|
18
18
|
enableV12DynamicFloatingStyles?: boolean;
|
|
19
19
|
enableEnhancedFileUploader?: boolean;
|
|
20
|
+
enablePresence?: boolean;
|
|
20
21
|
}
|
|
21
22
|
/**
|
|
22
23
|
* Our FeatureFlagContext is used alongside the FeatureFlags component to enable
|
|
@@ -28,7 +29,7 @@ declare const FeatureFlagContext: React.Context<any>;
|
|
|
28
29
|
* along with the current `FeatureFlagContext` to provide consumers to check if
|
|
29
30
|
* a feature flag is enabled or disabled in a given React tree
|
|
30
31
|
*/
|
|
31
|
-
declare function FeatureFlags({ children, flags, enableV12TileDefaultIcons, enableV12TileRadioIcons, enableV12Overflowmenu, enableTreeviewControllable, enableExperimentalFocusWrapWithoutSentinels, enableDialogElement, enableV12DynamicFloatingStyles, enableEnhancedFileUploader, }: FeatureFlagsProps): JSX.Element;
|
|
32
|
+
declare function FeatureFlags({ children, flags, enableV12TileDefaultIcons, enableV12TileRadioIcons, enableV12Overflowmenu, enableTreeviewControllable, enableExperimentalFocusWrapWithoutSentinels, enableDialogElement, enableV12DynamicFloatingStyles, enableEnhancedFileUploader, enablePresence, }: FeatureFlagsProps): JSX.Element;
|
|
32
33
|
declare namespace FeatureFlags {
|
|
33
34
|
var propTypes: {
|
|
34
35
|
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
@@ -32,7 +32,8 @@ function FeatureFlags({
|
|
|
32
32
|
enableExperimentalFocusWrapWithoutSentinels = false,
|
|
33
33
|
enableDialogElement = false,
|
|
34
34
|
enableV12DynamicFloatingStyles = false,
|
|
35
|
-
enableEnhancedFileUploader = false
|
|
35
|
+
enableEnhancedFileUploader = false,
|
|
36
|
+
enablePresence = false
|
|
36
37
|
}) {
|
|
37
38
|
const parentScope = useContext(FeatureFlagContext);
|
|
38
39
|
const [prevParentScope, setPrevParentScope] = useState(parentScope);
|
|
@@ -45,6 +46,7 @@ function FeatureFlags({
|
|
|
45
46
|
'enable-dialog-element': enableDialogElement,
|
|
46
47
|
'enable-v12-dynamic-floating-styles': enableV12DynamicFloatingStyles,
|
|
47
48
|
'enable-enhanced-file-uploader': enableEnhancedFileUploader,
|
|
49
|
+
'enable-presence': enablePresence,
|
|
48
50
|
...flags
|
|
49
51
|
};
|
|
50
52
|
const [scope, updateScope] = useState(() => {
|
|
@@ -15,10 +15,10 @@ import { ButtonKinds } from '../Button/Button.js';
|
|
|
15
15
|
import { Enter, Space } from '../../internal/keyboard/keys.js';
|
|
16
16
|
import { matches } from '../../internal/keyboard/match.js';
|
|
17
17
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
18
|
-
import '../Text/
|
|
18
|
+
import { Text } from '../Text/Text.js';
|
|
19
|
+
import '../Text/TextDirection.js';
|
|
19
20
|
import { useId } from '../../internal/useId.js';
|
|
20
21
|
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
21
|
-
import { Text } from '../Text/Text.js';
|
|
22
22
|
|
|
23
23
|
// eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20071
|
|
24
24
|
const FileUploader = /*#__PURE__*/React.forwardRef(({
|
|
@@ -15,10 +15,10 @@ import { matches } from '../../internal/keyboard/match.js';
|
|
|
15
15
|
import { useId } from '../../internal/useId.js';
|
|
16
16
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
17
17
|
import { noopFn } from '../../internal/noopFn.js';
|
|
18
|
-
import '../Text/
|
|
18
|
+
import { Text } from '../Text/Text.js';
|
|
19
|
+
import '../Text/TextDirection.js';
|
|
19
20
|
import '../Tooltip/DefinitionTooltip.js';
|
|
20
21
|
import { Tooltip } from '../Tooltip/Tooltip.js';
|
|
21
|
-
import { Text } from '../Text/Text.js';
|
|
22
22
|
|
|
23
23
|
function FileUploaderItem({
|
|
24
24
|
uuid,
|
|
@@ -5,13 +5,30 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
8
9
|
import PropTypes from 'prop-types';
|
|
9
|
-
import 'react';
|
|
10
|
-
import 'classnames';
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import cx from 'classnames';
|
|
11
12
|
import '../TextInput/ControlledPasswordInput.js';
|
|
12
|
-
import '../TextInput/PasswordInput.js';
|
|
13
|
+
import PasswordInput from '../TextInput/PasswordInput.js';
|
|
14
|
+
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
|
+
import { FormContext } from '../FluidForm/FormContext.js';
|
|
13
16
|
|
|
14
|
-
({
|
|
17
|
+
const FluidPasswordInput = ({
|
|
18
|
+
className,
|
|
19
|
+
...other
|
|
20
|
+
}) => {
|
|
21
|
+
const prefix = usePrefix();
|
|
22
|
+
const classNames = cx(className, `${prefix}--text-input--fluid`);
|
|
23
|
+
return /*#__PURE__*/React.createElement(FormContext.Provider, {
|
|
24
|
+
value: {
|
|
25
|
+
isFluid: true
|
|
26
|
+
}
|
|
27
|
+
}, /*#__PURE__*/React.createElement(PasswordInput, _extends({
|
|
28
|
+
className: classNames
|
|
29
|
+
}, other)));
|
|
30
|
+
};
|
|
31
|
+
FluidPasswordInput.propTypes = {
|
|
15
32
|
/**
|
|
16
33
|
* Specify an optional className to be applied to the outer FluidForm wrapper
|
|
17
34
|
*/
|
|
@@ -88,4 +105,6 @@ import '../TextInput/PasswordInput.js';
|
|
|
88
105
|
* Whether or not the component is readonly
|
|
89
106
|
*/
|
|
90
107
|
readOnly: PropTypes.bool
|
|
91
|
-
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export { FluidPasswordInput as default };
|
|
@@ -10,8 +10,8 @@ import PropTypes from 'prop-types';
|
|
|
10
10
|
import React from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
13
|
-
import '../Text/index.js';
|
|
14
13
|
import { Text } from '../Text/Text.js';
|
|
14
|
+
import '../Text/TextDirection.js';
|
|
15
15
|
|
|
16
16
|
function FormLabel({
|
|
17
17
|
className: customClassName,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import React, { type HTMLAttributes } from 'react';
|
|
8
|
-
import { type ListBoxSize, type ListBoxType } from '
|
|
8
|
+
import { type ListBoxSize, type ListBoxType } from './ListBoxPropTypes';
|
|
9
9
|
type ExcludedAttributes = 'onKeyDown' | 'onKeyPress' | 'ref';
|
|
10
10
|
export interface ListBoxProps extends Omit<HTMLAttributes<HTMLDivElement>, ExcludedAttributes> {
|
|
11
11
|
/**
|
|
@@ -10,11 +10,10 @@ import cx from 'classnames';
|
|
|
10
10
|
import React, { forwardRef, useContext } from 'react';
|
|
11
11
|
import PropTypes from 'prop-types';
|
|
12
12
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
13
|
-
import './
|
|
13
|
+
import { ListBoxTypePropType, ListBoxSizePropType } from './ListBoxPropTypes.js';
|
|
14
14
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
15
|
import '../FluidForm/FluidForm.js';
|
|
16
16
|
import { FormContext } from '../FluidForm/FormContext.js';
|
|
17
|
-
import { ListBoxTypePropType, ListBoxSizePropType } from './ListBoxPropTypes.js';
|
|
18
17
|
|
|
19
18
|
const handleOnKeyDown = event => {
|
|
20
19
|
if (event.keyCode === 27) {
|
|
@@ -10,8 +10,8 @@ import PropTypes from 'prop-types';
|
|
|
10
10
|
import React from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
13
|
-
import '../Text/index.js';
|
|
14
13
|
import { Text } from '../Text/Text.js';
|
|
14
|
+
import '../Text/TextDirection.js';
|
|
15
15
|
|
|
16
16
|
function ListItem({
|
|
17
17
|
className,
|
|
@@ -20,9 +20,9 @@ import { Menu } from './Menu.js';
|
|
|
20
20
|
import { MenuContext } from './MenuContext.js';
|
|
21
21
|
import '../LayoutDirection/LayoutDirection.js';
|
|
22
22
|
import { useLayoutDirection } from '../LayoutDirection/useLayoutDirection.js';
|
|
23
|
-
import '../Text/index.js';
|
|
24
|
-
import { defaultItemToString } from '../../internal/defaultItemToString.js';
|
|
25
23
|
import { Text } from '../Text/Text.js';
|
|
24
|
+
import '../Text/TextDirection.js';
|
|
25
|
+
import { defaultItemToString } from '../../internal/defaultItemToString.js';
|
|
26
26
|
|
|
27
27
|
var _Checkmark, _CaretLeft, _CaretRight;
|
|
28
28
|
const MenuItem = /*#__PURE__*/forwardRef(function MenuItem({
|
|
@@ -19,7 +19,7 @@ import { useId } from '../../internal/useId.js';
|
|
|
19
19
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
20
20
|
import { flip, size, useFloating, autoUpdate } from '@floating-ui/react';
|
|
21
21
|
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
22
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
22
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
23
23
|
|
|
24
24
|
const validButtonKinds = ['primary', 'tertiary', 'ghost'];
|
|
25
25
|
const defaultButtonKind = 'primary';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import PropTypes from 'prop-types';
|
|
10
|
-
import React, { useRef, useState, useEffect, cloneElement } from 'react';
|
|
10
|
+
import React, { useContext, useRef, useState, useEffect, cloneElement } from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { Close } from '@carbon/icons-react';
|
|
13
13
|
import { toggleClass } from '../../tools/toggleClass.js';
|
|
@@ -20,13 +20,15 @@ import { requiredIfGivenPropIsTruthy } from '../../prop-types/requiredIfGivenPro
|
|
|
20
20
|
import { wrapFocus, wrapFocusWithoutSentinels, elementOrParentIsFloatingMenu } from '../../internal/wrapFocus.js';
|
|
21
21
|
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
22
22
|
import { useId } from '../../internal/useId.js';
|
|
23
|
+
import { useMergedRefs } from '../../internal/useMergedRefs.js';
|
|
23
24
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
24
25
|
import { usePreviousValue } from '../../internal/usePreviousValue.js';
|
|
25
26
|
import { Escape, Enter, Tab } from '../../internal/keyboard/keys.js';
|
|
26
27
|
import { match } from '../../internal/keyboard/match.js';
|
|
27
28
|
import { IconButton } from '../IconButton/index.js';
|
|
28
29
|
import { noopFn } from '../../internal/noopFn.js';
|
|
29
|
-
import '../Text/
|
|
30
|
+
import { Text } from '../Text/Text.js';
|
|
31
|
+
import '../Text/TextDirection.js';
|
|
30
32
|
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
31
33
|
import { composeEventHandlers } from '../../tools/events.js';
|
|
32
34
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
@@ -34,12 +36,40 @@ import { Dialog } from '../Dialog/Dialog.js';
|
|
|
34
36
|
import { AILabel } from '../AILabel/index.js';
|
|
35
37
|
import { isComponentElement } from '../../internal/utils.js';
|
|
36
38
|
import { warning } from '../../internal/warning.js';
|
|
39
|
+
import { ModalPresenceContext, useExclusiveModalPresenceContext, ModalPresence } from './ModalPresence.js';
|
|
37
40
|
import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.js';
|
|
38
|
-
import { Text } from '../Text/Text.js';
|
|
39
41
|
|
|
40
42
|
const ModalSizes = ['xs', 'sm', 'md', 'lg'];
|
|
41
43
|
const invalidOutsideClickMessage = '`<Modal>` prop `preventCloseOnClickOutside` should not be `false` when ' + '`passiveModal` is `false`. Transactional, non-passive Modals should ' + 'not be dissmissable by clicking outside. ' + 'See: https://carbondesignsystem.com/components/modal/usage/#transactional-modal';
|
|
42
44
|
const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
45
|
+
open,
|
|
46
|
+
...props
|
|
47
|
+
}, ref) {
|
|
48
|
+
const id = useId();
|
|
49
|
+
const enablePresence = useFeatureFlag('enable-presence');
|
|
50
|
+
const hasPresenceContext = Boolean(useContext(ModalPresenceContext));
|
|
51
|
+
const hasPresenceOptIn = enablePresence || hasPresenceContext;
|
|
52
|
+
const exclusivePresenceContext = useExclusiveModalPresenceContext(id);
|
|
53
|
+
|
|
54
|
+
// if opt in and not exclusive to a presence context, wrap with presence
|
|
55
|
+
if (hasPresenceOptIn && !exclusivePresenceContext) {
|
|
56
|
+
return /*#__PURE__*/React.createElement(ModalPresence, {
|
|
57
|
+
open: open ?? false,
|
|
58
|
+
_presenceId: id
|
|
59
|
+
// do not auto enable styles for opt-in by feature flag
|
|
60
|
+
,
|
|
61
|
+
_autoEnablePresence: hasPresenceContext
|
|
62
|
+
}, /*#__PURE__*/React.createElement(ModalDialog, _extends({
|
|
63
|
+
open: true,
|
|
64
|
+
ref: ref
|
|
65
|
+
}, props)));
|
|
66
|
+
}
|
|
67
|
+
return /*#__PURE__*/React.createElement(ModalDialog, _extends({
|
|
68
|
+
ref: ref,
|
|
69
|
+
open: open
|
|
70
|
+
}, props));
|
|
71
|
+
});
|
|
72
|
+
const ModalDialog = /*#__PURE__*/React.forwardRef(function ModalDialog({
|
|
43
73
|
'aria-label': ariaLabelProp,
|
|
44
74
|
children,
|
|
45
75
|
className,
|
|
@@ -50,7 +80,7 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
|
50
80
|
passiveModal = false,
|
|
51
81
|
secondaryButtonText,
|
|
52
82
|
primaryButtonText,
|
|
53
|
-
open,
|
|
83
|
+
open: externalOpen,
|
|
54
84
|
onRequestClose = noopFn,
|
|
55
85
|
onRequestSubmit = noopFn,
|
|
56
86
|
onSecondarySubmit,
|
|
@@ -83,7 +113,6 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
|
83
113
|
const endTrap = useRef(null);
|
|
84
114
|
const wrapFocusTimeout = useRef(null);
|
|
85
115
|
const [isScrollable, setIsScrollable] = useState(false);
|
|
86
|
-
const prevOpen = usePreviousValue(open);
|
|
87
116
|
const modalInstanceId = `modal-${useId()}`;
|
|
88
117
|
const modalLabelId = `${prefix}--modal-header__label--${modalInstanceId}`;
|
|
89
118
|
const modalHeadingId = `${prefix}--modal-header__heading--${modalInstanceId}`;
|
|
@@ -93,6 +122,13 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
|
93
122
|
[`${prefix}--btn--loading`]: loadingStatus !== 'inactive'
|
|
94
123
|
});
|
|
95
124
|
const loadingActive = loadingStatus !== 'inactive';
|
|
125
|
+
const presenceContext = useContext(ModalPresenceContext);
|
|
126
|
+
const mergedRefs = useMergedRefs([ref, presenceContext?.presenceRef]);
|
|
127
|
+
const enablePresence = useFeatureFlag('enable-presence') || presenceContext?.autoEnablePresence;
|
|
128
|
+
|
|
129
|
+
// always mark as open when mounted with presence
|
|
130
|
+
const open = externalOpen || enablePresence;
|
|
131
|
+
const prevOpen = usePreviousValue(open);
|
|
96
132
|
const focusTrapWithoutSentinels = useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
|
|
97
133
|
const enableDialogElement = useFeatureFlag('enable-dialog-element');
|
|
98
134
|
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;
|
|
@@ -188,7 +224,8 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
|
188
224
|
const onSecondaryButtonClick = onSecondarySubmit ? onSecondarySubmit : onRequestClose;
|
|
189
225
|
const modalClasses = cx(`${prefix}--modal`, {
|
|
190
226
|
[`${prefix}--modal-tall`]: !passiveModal,
|
|
191
|
-
'is-visible': open,
|
|
227
|
+
'is-visible': enablePresence || open,
|
|
228
|
+
[`${prefix}--modal--enable-presence`]: presenceContext?.autoEnablePresence,
|
|
192
229
|
[`${prefix}--modal--danger`]: danger,
|
|
193
230
|
[`${prefix}--modal--slug`]: slug,
|
|
194
231
|
[`${prefix}--modal--decorator`]: decorator
|
|
@@ -252,14 +289,25 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
|
252
289
|
}
|
|
253
290
|
}, [open, prefix, enableDialogElement]);
|
|
254
291
|
useEffect(() => {
|
|
255
|
-
if (!enableDialogElement && prevOpen && !open && launcherButtonRef) {
|
|
292
|
+
if (!enableDialogElement && !enablePresence && prevOpen && !open && launcherButtonRef) {
|
|
256
293
|
setTimeout(() => {
|
|
257
294
|
if ('current' in launcherButtonRef) {
|
|
258
295
|
launcherButtonRef.current?.focus();
|
|
259
296
|
}
|
|
260
297
|
});
|
|
261
298
|
}
|
|
262
|
-
}, [open, prevOpen, launcherButtonRef, enableDialogElement]);
|
|
299
|
+
}, [open, prevOpen, launcherButtonRef, enableDialogElement, enablePresence]);
|
|
300
|
+
// Focus launcherButtonRef on unmount
|
|
301
|
+
useEffect(() => {
|
|
302
|
+
const launcherButton = launcherButtonRef?.current;
|
|
303
|
+
return () => {
|
|
304
|
+
if (enablePresence && launcherButton) {
|
|
305
|
+
setTimeout(() => {
|
|
306
|
+
launcherButton.focus();
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}, [enablePresence, launcherButtonRef]);
|
|
263
311
|
useEffect(() => {
|
|
264
312
|
if (!enableDialogElement) {
|
|
265
313
|
const initialFocus = focusContainerElement => {
|
|
@@ -331,7 +379,8 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
|
331
379
|
role: isAlertDialog ? 'alertdialog' : '',
|
|
332
380
|
"aria-describedby": isAlertDialog ? modalBodyId : '',
|
|
333
381
|
className: containerClasses,
|
|
334
|
-
"aria-label": ariaLabel
|
|
382
|
+
"aria-label": ariaLabel,
|
|
383
|
+
"data-exiting": presenceContext?.isExiting || undefined
|
|
335
384
|
}, /*#__PURE__*/React.createElement("div", {
|
|
336
385
|
className: `${prefix}--modal-header`
|
|
337
386
|
}, modalLabel && /*#__PURE__*/React.createElement(Text, {
|
|
@@ -458,7 +507,8 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
|
|
|
458
507
|
onBlur: handleBlur,
|
|
459
508
|
className: modalClasses,
|
|
460
509
|
role: "presentation",
|
|
461
|
-
ref:
|
|
510
|
+
ref: mergedRefs,
|
|
511
|
+
"data-exiting": presenceContext?.isExiting || undefined
|
|
462
512
|
}), modalBody);
|
|
463
513
|
});
|
|
464
514
|
Modal.propTypes = {
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
export interface ModalPresenceProps {
|
|
10
|
+
/**
|
|
11
|
+
* Specify whether the Modal is currently open
|
|
12
|
+
*/
|
|
13
|
+
open: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Internal property for backwards compatibility. Specify whether the Modal should opt in to presence mode.
|
|
16
|
+
*/
|
|
17
|
+
_autoEnablePresence?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Internal property to predefine the presence context's id for exclusivity.
|
|
20
|
+
*/
|
|
21
|
+
_presenceId?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const ModalPresence: ({ open, _presenceId: presenceId, _autoEnablePresence: autoEnablePresence, children, }: PropsWithChildren<ModalPresenceProps>) => import("react/jsx-runtime").JSX.Element | null;
|
|
24
|
+
interface ModalPresenceContextProps extends PresenceContext {
|
|
25
|
+
autoEnablePresence: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare const ModalPresenceContext: React.Context<ModalPresenceContextProps | undefined>;
|
|
28
|
+
/**
|
|
29
|
+
* Handles occurrences where only a single modal must consume a context.
|
|
30
|
+
*/
|
|
31
|
+
export declare const useExclusiveModalPresenceContext: (id: string) => ModalPresenceContextProps | undefined;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
|
|
11
|
+
const ModalPresence = ({
|
|
12
|
+
open,
|
|
13
|
+
_presenceId: presenceId,
|
|
14
|
+
_autoEnablePresence: autoEnablePresence = true,
|
|
15
|
+
children
|
|
16
|
+
}) => {
|
|
17
|
+
const [isPresent, context] = usePresenceContext(open, presenceId);
|
|
18
|
+
const contextValue = useMemo(() => ({
|
|
19
|
+
autoEnablePresence,
|
|
20
|
+
...context
|
|
21
|
+
}), [autoEnablePresence, context]);
|
|
22
|
+
if (!isPresent) return null;
|
|
23
|
+
return /*#__PURE__*/React.createElement(ModalPresenceContext.Provider, {
|
|
24
|
+
value: contextValue
|
|
25
|
+
}, children);
|
|
26
|
+
};
|
|
27
|
+
const ModalPresenceContext = /*#__PURE__*/createContext(undefined);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Handles occurrences where only a single modal must consume a context.
|
|
31
|
+
*/
|
|
32
|
+
const useExclusiveModalPresenceContext = id => {
|
|
33
|
+
const ctx = useContext(ModalPresenceContext);
|
|
34
|
+
return ctx?.isPresenceExclusive(id) ? ctx : undefined;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { ModalPresence, ModalPresenceContext, useExclusiveModalPresenceContext };
|
|
@@ -5,5 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import Modal, { type ModalProps } from './Modal';
|
|
8
|
+
import { ModalPresence, type ModalPresenceProps } from './ModalPresence';
|
|
8
9
|
export default Modal;
|
|
9
|
-
export { Modal, type ModalProps };
|
|
10
|
+
export { Modal, ModalPresence, type ModalProps, type ModalPresenceProps };
|
|
@@ -21,7 +21,7 @@ import ListBoxSelection from '../ListBox/next/ListBoxSelection.js';
|
|
|
21
21
|
import ListBoxTrigger from '../ListBox/next/ListBoxTrigger.js';
|
|
22
22
|
import { Space, Enter, Delete, Escape, Tab, Home, End } from '../../internal/keyboard/keys.js';
|
|
23
23
|
import { match } from '../../internal/keyboard/match.js';
|
|
24
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
24
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
25
25
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
26
26
|
import { useId } from '../../internal/useId.js';
|
|
27
27
|
import { defaultSortItems, defaultCompareItems } from './tools/sorting.js';
|
|
@@ -629,8 +629,8 @@ const FilterableMultiSelect = /*#__PURE__*/forwardRef(function FilterableMultiSe
|
|
|
629
629
|
// NOTE: does not prevent click
|
|
630
630
|
evt.preventDefault();
|
|
631
631
|
// focus on the element as per readonly input behavior
|
|
632
|
-
if (
|
|
633
|
-
|
|
632
|
+
if (textInput.current) {
|
|
633
|
+
textInput.current.focus();
|
|
634
634
|
}
|
|
635
635
|
},
|
|
636
636
|
onKeyDown: evt => {
|
|
@@ -11,13 +11,13 @@ import cx from 'classnames';
|
|
|
11
11
|
import { useSelect } from 'downshift';
|
|
12
12
|
import isEqual from 'react-fast-compare';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
|
-
import React, { useMemo, useContext, useState, useLayoutEffect, isValidElement, useCallback, cloneElement } from 'react';
|
|
14
|
+
import React, { useMemo, useContext, useState, useLayoutEffect, useRef, isValidElement, useCallback, cloneElement } from 'react';
|
|
15
15
|
import ListBox from '../ListBox/index.js';
|
|
16
16
|
import { sortingPropTypes } from './MultiSelectPropTypes.js';
|
|
17
17
|
import { defaultSortItems, defaultCompareItems } from './tools/sorting.js';
|
|
18
18
|
import { useSelection } from '../../internal/Selection.js';
|
|
19
19
|
import { useId } from '../../internal/useId.js';
|
|
20
|
-
import mergeRefs from '../../tools/mergeRefs.js';
|
|
20
|
+
import { mergeRefs } from '../../tools/mergeRefs.js';
|
|
21
21
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
22
22
|
import { Delete, Escape, Space, ArrowDown, Enter } from '../../internal/keyboard/keys.js';
|
|
23
23
|
import { match } from '../../internal/keyboard/match.js';
|
|
@@ -233,7 +233,8 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
});
|
|
236
|
-
const
|
|
236
|
+
const toggleButtonRef = useRef(null);
|
|
237
|
+
const mergedRef = mergeRefs(toggleButtonProps.ref, ref, toggleButtonRef);
|
|
237
238
|
const selectedItems = selectedItem;
|
|
238
239
|
|
|
239
240
|
/**
|
|
@@ -388,8 +389,8 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
|
|
|
388
389
|
// NOTE: does not prevent click
|
|
389
390
|
evt.preventDefault();
|
|
390
391
|
// focus on the element as per readonly input behavior
|
|
391
|
-
if (
|
|
392
|
-
|
|
392
|
+
if (toggleButtonRef.current) {
|
|
393
|
+
toggleButtonRef.current.focus();
|
|
393
394
|
}
|
|
394
395
|
},
|
|
395
396
|
onKeyDown: evt => {
|
|
@@ -11,7 +11,8 @@ import React, { useState, useRef, useEffect } from 'react';
|
|
|
11
11
|
import { deprecate } from '../../prop-types/deprecate.js';
|
|
12
12
|
import cx from 'classnames';
|
|
13
13
|
import { Close, InformationSquareFilled, InformationFilled, WarningAltFilled, WarningFilled, CheckmarkFilled, ErrorFilled } from '@carbon/icons-react';
|
|
14
|
-
import '../Text/
|
|
14
|
+
import { Text } from '../Text/Text.js';
|
|
15
|
+
import '../Text/TextDirection.js';
|
|
15
16
|
import Button from '../Button/Button.js';
|
|
16
17
|
import '../Button/Button.Skeleton.js';
|
|
17
18
|
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
@@ -25,7 +26,6 @@ import { wrapFocusWithoutSentinels, wrapFocus } from '../../internal/wrapFocus.j
|
|
|
25
26
|
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
26
27
|
import { warning } from '../../internal/warning.js';
|
|
27
28
|
import { deprecateValuesWithin } from '../../prop-types/deprecateValuesWithin.js';
|
|
28
|
-
import { Text } from '../Text/Text.js';
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Conditionally call a callback when the escape key is pressed
|
|
@@ -17,6 +17,26 @@ export declare const translationIds: {
|
|
|
17
17
|
type TranslationKey = keyof typeof translationIds;
|
|
18
18
|
type ExcludedAttributes = 'defaultValue' | 'id' | 'min' | 'max' | 'onChange' | 'onClick' | 'size' | 'step' | 'value';
|
|
19
19
|
export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, ExcludedAttributes>, TranslateWithId<TranslationKey> {
|
|
20
|
+
/**
|
|
21
|
+
* Optional validation function that is called with the input value and locale.
|
|
22
|
+
* This is called before other validations, giving consumers the ability
|
|
23
|
+
* to short-circuit or extend validation without replacing built-in rules
|
|
24
|
+
* @example
|
|
25
|
+
* // Using the built-in separator validation
|
|
26
|
+
* <NumberInput validate={validateNumberSeparators} />
|
|
27
|
+
*
|
|
28
|
+
* // Combining with custom validation
|
|
29
|
+
* <NumberInput
|
|
30
|
+
* validate={(value, locale) => {
|
|
31
|
+
* return validateNumberSeparators(value, locale) && customValidation(value)
|
|
32
|
+
* }}
|
|
33
|
+
* />
|
|
34
|
+
* - Return `false` to immediately fail validation.
|
|
35
|
+
* - Return `true` to pass this validation, but still run other checks (min, max, required, etc.).
|
|
36
|
+
* - Return `undefined` to defer entirely to built-in validation logic.
|
|
37
|
+
*
|
|
38
|
+
*/
|
|
39
|
+
validate?: (value: string, locale: string) => boolean | undefined;
|
|
20
40
|
/**
|
|
21
41
|
* `true` to allow empty string.
|
|
22
42
|
*/
|
|
@@ -186,16 +206,6 @@ export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInp
|
|
|
186
206
|
*/
|
|
187
207
|
warnText?: ReactNode;
|
|
188
208
|
}
|
|
209
|
+
export declare const validateNumberSeparators: (input: string, locale: string) => boolean;
|
|
189
210
|
declare const NumberInput: React.ForwardRefExoticComponent<NumberInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
190
|
-
export interface Label {
|
|
191
|
-
disabled?: boolean;
|
|
192
|
-
hideLabel?: boolean;
|
|
193
|
-
id?: string;
|
|
194
|
-
label?: ReactNode;
|
|
195
|
-
}
|
|
196
|
-
export interface HelperTextProps {
|
|
197
|
-
id?: string;
|
|
198
|
-
description?: ReactNode;
|
|
199
|
-
disabled?: boolean;
|
|
200
|
-
}
|
|
201
211
|
export { NumberInput };
|