@carbon/react 1.68.0 → 1.69.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 +786 -786
- package/README.md +3 -3
- package/es/components/Accordion/AccordionItem.js +0 -1
- package/es/components/Button/Button.js +6 -0
- package/es/components/CheckboxGroup/CheckboxGroup.js +1 -2
- package/es/components/CheckboxGroup/index.d.ts +10 -0
- package/es/components/ComboBox/ComboBox.js +13 -18
- package/es/components/ComboButton/index.js +10 -3
- package/es/components/DataTable/TableCell.d.ts +1 -4
- package/es/components/DataTable/TableCell.js +3 -2
- package/es/components/Disclosure/index.d.ts +18 -0
- package/es/components/Dropdown/Dropdown.js +11 -9
- package/es/components/FileUploader/FileUploader.d.ts +8 -92
- package/es/components/FileUploader/FileUploader.js +116 -137
- package/es/components/IdPrefix/index.d.ts +26 -0
- package/es/components/Menu/MenuItem.js +1 -4
- package/es/components/MenuButton/index.d.ts +4 -0
- package/es/components/MenuButton/index.js +19 -5
- package/es/components/MultiSelect/MultiSelect.js +11 -9
- package/es/components/OverflowMenu/next/index.d.ts +4 -0
- package/es/components/OverflowMenu/next/index.js +19 -9
- package/es/components/PaginationNav/PaginationNav.js +1 -1
- package/es/components/Popover/index.js +18 -14
- package/es/components/Portal/index.d.ts +25 -0
- package/es/components/Slider/Slider.js +2 -2
- package/es/components/Tag/DismissibleTag.js +2 -2
- package/es/components/Tag/OperationalTag.d.ts +2 -10
- package/es/components/Tag/OperationalTag.js +2 -14
- package/es/components/Tag/SelectableTag.d.ts +2 -10
- package/es/components/Tag/SelectableTag.js +2 -16
- package/es/components/Toggle/Toggle.js +2 -0
- package/es/components/ToggleSmall/ToggleSmall.Skeleton.d.ts +49 -0
- package/es/components/ToggleSmall/index.d.ts +7 -0
- package/es/components/TreeView/TreeNode.js +4 -2
- package/es/components/TreeView/TreeView.js +4 -4
- package/es/components/UIShell/SideNavMenuItem.d.ts +4 -3
- package/es/components/UIShell/SideNavMenuItem.js +1 -4
- package/es/index.js +1 -1
- package/es/internal/useIdPrefix.d.ts +9 -0
- package/lib/components/Accordion/AccordionItem.js +0 -1
- package/lib/components/Button/Button.js +6 -0
- package/lib/components/CheckboxGroup/CheckboxGroup.js +1 -2
- package/lib/components/CheckboxGroup/index.d.ts +10 -0
- package/lib/components/ComboBox/ComboBox.js +18 -23
- package/lib/components/ComboButton/index.js +12 -5
- package/lib/components/DataTable/TableCell.d.ts +1 -4
- package/lib/components/DataTable/TableCell.js +3 -2
- package/lib/components/Disclosure/index.d.ts +18 -0
- package/lib/components/Dropdown/Dropdown.js +18 -16
- package/lib/components/FileUploader/FileUploader.d.ts +8 -92
- package/lib/components/FileUploader/FileUploader.js +113 -134
- package/lib/components/IdPrefix/index.d.ts +26 -0
- package/lib/components/Menu/MenuItem.js +1 -4
- package/lib/components/MenuButton/index.d.ts +4 -0
- package/lib/components/MenuButton/index.js +19 -5
- package/lib/components/MultiSelect/MultiSelect.js +18 -16
- package/lib/components/OverflowMenu/next/index.d.ts +4 -0
- package/lib/components/OverflowMenu/next/index.js +21 -11
- package/lib/components/PaginationNav/PaginationNav.js +1 -1
- package/lib/components/Popover/index.js +18 -14
- package/lib/components/Portal/index.d.ts +25 -0
- package/lib/components/Slider/Slider.js +2 -2
- package/lib/components/Tag/DismissibleTag.js +2 -2
- package/lib/components/Tag/OperationalTag.d.ts +2 -10
- package/lib/components/Tag/OperationalTag.js +2 -14
- package/lib/components/Tag/SelectableTag.d.ts +2 -10
- package/lib/components/Tag/SelectableTag.js +2 -16
- package/lib/components/Toggle/Toggle.js +2 -0
- package/lib/components/ToggleSmall/ToggleSmall.Skeleton.d.ts +49 -0
- package/lib/components/ToggleSmall/index.d.ts +7 -0
- package/lib/components/TreeView/TreeNode.js +4 -2
- package/lib/components/TreeView/TreeView.js +4 -4
- package/lib/components/UIShell/SideNavMenuItem.d.ts +4 -3
- package/lib/components/UIShell/SideNavMenuItem.js +1 -4
- package/lib/index.js +2 -2
- package/lib/internal/useIdPrefix.d.ts +9 -0
- package/package.json +7 -7
- package/telemetry.yml +809 -809
|
@@ -5,157 +5,137 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import cx from 'classnames';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
|
-
import React__default from 'react';
|
|
11
|
+
import React__default, { useState } from 'react';
|
|
12
12
|
import Filename from './Filename.js';
|
|
13
13
|
import FileUploaderButton from './FileUploaderButton.js';
|
|
14
14
|
import { ButtonKinds } from '../../prop-types/types.js';
|
|
15
|
-
import {
|
|
15
|
+
import { usePrefix } from '../../internal/usePrefix.js';
|
|
16
16
|
import '../Text/index.js';
|
|
17
|
+
import { useId } from '../../internal/useId.js';
|
|
17
18
|
import { Text } from '../Text/Text.js';
|
|
18
19
|
import { matches } from '../../internal/keyboard/match.js';
|
|
19
20
|
import { Enter, Space } from '../../internal/keyboard/keys.js';
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
const FileUploader = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
23
|
+
let {
|
|
24
|
+
accept,
|
|
25
|
+
buttonKind,
|
|
26
|
+
buttonLabel,
|
|
27
|
+
className,
|
|
28
|
+
disabled,
|
|
29
|
+
filenameStatus,
|
|
30
|
+
iconDescription,
|
|
31
|
+
labelDescription,
|
|
32
|
+
labelTitle,
|
|
33
|
+
multiple,
|
|
34
|
+
name,
|
|
35
|
+
onChange,
|
|
36
|
+
onClick,
|
|
37
|
+
onDelete,
|
|
38
|
+
size,
|
|
39
|
+
...other
|
|
40
|
+
} = _ref;
|
|
41
|
+
const fileUploaderInstanceId = useId('file-uploader');
|
|
42
|
+
const [state, updateState] = useState({
|
|
43
|
+
fileNames: []
|
|
44
|
+
});
|
|
45
|
+
const nodes = [];
|
|
46
|
+
const prefix = usePrefix();
|
|
47
|
+
const handleChange = evt => {
|
|
48
|
+
evt.stopPropagation();
|
|
49
|
+
const filenames = Array.prototype.map.call(evt.target.files, file => file.name);
|
|
50
|
+
updateState(prevState => ({
|
|
51
|
+
fileNames: multiple ? [...new Set([...prevState.fileNames, ...filenames])] : filenames
|
|
52
|
+
}));
|
|
53
|
+
if (onChange) {
|
|
54
|
+
onChange(evt);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const handleClick = (evt, _ref2) => {
|
|
58
|
+
let {
|
|
59
|
+
index,
|
|
60
|
+
filenameStatus
|
|
61
|
+
} = _ref2;
|
|
62
|
+
if (filenameStatus === 'edit') {
|
|
30
63
|
evt.stopPropagation();
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
64
|
+
const filteredArray = state.fileNames.filter(filename => filename !== nodes[index]?.innerText?.trim());
|
|
65
|
+
updateState({
|
|
66
|
+
fileNames: filteredArray
|
|
34
67
|
});
|
|
35
|
-
if (
|
|
36
|
-
|
|
68
|
+
if (onDelete) {
|
|
69
|
+
onDelete(evt);
|
|
70
|
+
uploaderButton.current?.focus?.();
|
|
37
71
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
72
|
+
onClick?.(evt);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const uploaderButton = /*#__PURE__*/React__default.createRef();
|
|
76
|
+
const classes = cx({
|
|
77
|
+
[`${prefix}--form-item`]: true,
|
|
78
|
+
[className]: className
|
|
79
|
+
});
|
|
80
|
+
const getHelperLabelClasses = baseClass => cx(baseClass, {
|
|
81
|
+
[`${prefix}--label-description--disabled`]: disabled
|
|
82
|
+
});
|
|
83
|
+
const selectedFileClasses = cx(`${prefix}--file__selected-file`, {
|
|
84
|
+
[`${prefix}--file__selected-file--md`]: size === 'field' || size === 'md',
|
|
85
|
+
[`${prefix}--file__selected-file--sm`]: size === 'small' || size === 'sm'
|
|
86
|
+
});
|
|
87
|
+
return /*#__PURE__*/React__default.createElement("div", _extends({
|
|
88
|
+
className: classes
|
|
89
|
+
}, other), !labelTitle ? null : /*#__PURE__*/React__default.createElement(Text, {
|
|
90
|
+
as: "h3",
|
|
91
|
+
className: getHelperLabelClasses(`${prefix}--file--label`)
|
|
92
|
+
}, labelTitle), /*#__PURE__*/React__default.createElement(Text, {
|
|
93
|
+
as: "p",
|
|
94
|
+
className: getHelperLabelClasses(`${prefix}--label-description`),
|
|
95
|
+
id: fileUploaderInstanceId
|
|
96
|
+
}, labelDescription), /*#__PURE__*/React__default.createElement(FileUploaderButton, {
|
|
97
|
+
innerRef: uploaderButton,
|
|
98
|
+
disabled: disabled,
|
|
99
|
+
labelText: buttonLabel,
|
|
100
|
+
multiple: multiple,
|
|
101
|
+
buttonKind: buttonKind,
|
|
102
|
+
onChange: handleChange,
|
|
103
|
+
disableLabelChanges: true,
|
|
104
|
+
accept: accept,
|
|
105
|
+
name: name,
|
|
106
|
+
size: size,
|
|
107
|
+
"aria-describedby": fileUploaderInstanceId
|
|
108
|
+
}), /*#__PURE__*/React__default.createElement("div", {
|
|
109
|
+
className: `${prefix}--file-container`
|
|
110
|
+
}, state.fileNames.length === 0 ? null : state.fileNames.map((name, index) => /*#__PURE__*/React__default.createElement("span", _extends({
|
|
111
|
+
key: index,
|
|
112
|
+
className: selectedFileClasses,
|
|
113
|
+
ref: node => nodes[index] = node // eslint-disable-line
|
|
114
|
+
}, other), /*#__PURE__*/React__default.createElement(Text, {
|
|
115
|
+
as: "p",
|
|
116
|
+
className: `${prefix}--file-filename`,
|
|
117
|
+
id: name
|
|
118
|
+
}, name), /*#__PURE__*/React__default.createElement("span", {
|
|
119
|
+
className: `${prefix}--file__state-container`
|
|
120
|
+
}, /*#__PURE__*/React__default.createElement(Filename, {
|
|
121
|
+
name: name,
|
|
122
|
+
iconDescription: iconDescription,
|
|
123
|
+
status: filenameStatus,
|
|
124
|
+
onKeyDown: evt => {
|
|
125
|
+
if (matches(evt, [Enter, Space])) {
|
|
126
|
+
handleClick(evt, {
|
|
127
|
+
index,
|
|
128
|
+
filenameStatus
|
|
49
129
|
});
|
|
50
|
-
if (this.props.onDelete) {
|
|
51
|
-
this.props.onDelete(evt);
|
|
52
|
-
this.uploaderButton.current?.focus?.();
|
|
53
|
-
}
|
|
54
|
-
this.props.onClick?.(evt);
|
|
55
130
|
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.setState({
|
|
60
|
-
filenames: []
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
static getDerivedStateFromProps(_ref2, state) {
|
|
65
|
-
let {
|
|
131
|
+
},
|
|
132
|
+
onClick: evt => handleClick(evt, {
|
|
133
|
+
index,
|
|
66
134
|
filenameStatus
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return prevFilenameStatus === filenameStatus ? null : {
|
|
72
|
-
filenameStatus,
|
|
73
|
-
prevFilenameStatus: filenameStatus
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
render() {
|
|
77
|
-
const {
|
|
78
|
-
iconDescription,
|
|
79
|
-
buttonLabel = '',
|
|
80
|
-
buttonKind = 'primary',
|
|
81
|
-
disabled = false,
|
|
82
|
-
filenameStatus = 'uploading',
|
|
83
|
-
labelDescription,
|
|
84
|
-
labelTitle,
|
|
85
|
-
className,
|
|
86
|
-
multiple = false,
|
|
87
|
-
accept = [],
|
|
88
|
-
name,
|
|
89
|
-
size = 'md',
|
|
90
|
-
onDelete,
|
|
91
|
-
// eslint-disable-line
|
|
92
|
-
...other
|
|
93
|
-
} = this.props;
|
|
94
|
-
const prefix = this.context;
|
|
95
|
-
const classes = cx({
|
|
96
|
-
[`${prefix}--form-item`]: true,
|
|
97
|
-
[className]: className
|
|
98
|
-
});
|
|
99
|
-
const getHelperLabelClasses = baseClass => cx(baseClass, {
|
|
100
|
-
[`${prefix}--label-description--disabled`]: disabled
|
|
101
|
-
});
|
|
102
|
-
const selectedFileClasses = cx(`${prefix}--file__selected-file`, {
|
|
103
|
-
[`${prefix}--file__selected-file--md`]: size === 'field' || size === 'md',
|
|
104
|
-
[`${prefix}--file__selected-file--sm`]: size === 'small' || size === 'sm'
|
|
105
|
-
});
|
|
106
|
-
return /*#__PURE__*/React__default.createElement("div", _extends({
|
|
107
|
-
className: classes
|
|
108
|
-
}, other), !labelTitle ? null : /*#__PURE__*/React__default.createElement(Text, {
|
|
109
|
-
as: "h3",
|
|
110
|
-
className: getHelperLabelClasses(`${prefix}--file--label`)
|
|
111
|
-
}, labelTitle), /*#__PURE__*/React__default.createElement(Text, {
|
|
112
|
-
as: "p",
|
|
113
|
-
className: getHelperLabelClasses(`${prefix}--label-description`),
|
|
114
|
-
id: "description"
|
|
115
|
-
}, labelDescription), /*#__PURE__*/React__default.createElement(FileUploaderButton, {
|
|
116
|
-
innerRef: this.uploaderButton,
|
|
117
|
-
disabled: disabled,
|
|
118
|
-
labelText: buttonLabel,
|
|
119
|
-
multiple: multiple,
|
|
120
|
-
buttonKind: buttonKind,
|
|
121
|
-
onChange: this.handleChange,
|
|
122
|
-
disableLabelChanges: true,
|
|
123
|
-
accept: accept,
|
|
124
|
-
name: name,
|
|
125
|
-
size: size,
|
|
126
|
-
"aria-describedby": "description"
|
|
127
|
-
}), /*#__PURE__*/React__default.createElement("div", {
|
|
128
|
-
className: `${prefix}--file-container`
|
|
129
|
-
}, this.state.filenames.length === 0 ? null : this.state.filenames.map((name, index) => /*#__PURE__*/React__default.createElement("span", _extends({
|
|
130
|
-
key: index,
|
|
131
|
-
className: selectedFileClasses,
|
|
132
|
-
ref: node => this.nodes[index] = node // eslint-disable-line
|
|
133
|
-
}, other), /*#__PURE__*/React__default.createElement(Text, {
|
|
134
|
-
as: "p",
|
|
135
|
-
className: `${prefix}--file-filename`,
|
|
136
|
-
id: name
|
|
137
|
-
}, name), /*#__PURE__*/React__default.createElement("span", {
|
|
138
|
-
className: `${prefix}--file__state-container`
|
|
139
|
-
}, /*#__PURE__*/React__default.createElement(Filename, {
|
|
140
|
-
name: name,
|
|
141
|
-
iconDescription: iconDescription,
|
|
142
|
-
status: filenameStatus,
|
|
143
|
-
onKeyDown: evt => {
|
|
144
|
-
if (matches(evt, [Enter, Space])) {
|
|
145
|
-
this.handleClick(evt, {
|
|
146
|
-
index,
|
|
147
|
-
filenameStatus
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
onClick: evt => this.handleClick(evt, {
|
|
152
|
-
index,
|
|
153
|
-
filenameStatus
|
|
154
|
-
})
|
|
155
|
-
}))))));
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
_defineProperty(FileUploader, "propTypes", {
|
|
135
|
+
})
|
|
136
|
+
}))))));
|
|
137
|
+
});
|
|
138
|
+
FileUploader.propTypes = {
|
|
159
139
|
/**
|
|
160
140
|
* Specify the types of files that this input should be able to receive
|
|
161
141
|
*/
|
|
@@ -221,7 +201,6 @@ _defineProperty(FileUploader, "propTypes", {
|
|
|
221
201
|
* sizes.
|
|
222
202
|
*/
|
|
223
203
|
size: PropTypes.oneOf(['sm', 'md', 'lg'])
|
|
224
|
-
}
|
|
225
|
-
_defineProperty(FileUploader, "contextType", PrefixContext);
|
|
204
|
+
};
|
|
226
205
|
|
|
227
206
|
export { FileUploader as default };
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import { PropsWithChildren, ReactNode } from 'react';
|
|
9
|
+
type IdPrefixProps = {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* The value used to prefix the auto-generated id placed on some DOM elements
|
|
13
|
+
*/
|
|
14
|
+
prefix?: string;
|
|
15
|
+
};
|
|
16
|
+
declare function IdPrefix({ children, prefix }: PropsWithChildren<IdPrefixProps>): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
declare namespace IdPrefix {
|
|
18
|
+
var propTypes: {
|
|
19
|
+
children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
20
|
+
/**
|
|
21
|
+
* The value used to prefix the auto-generated id placed on some DOM elements
|
|
22
|
+
*/
|
|
23
|
+
prefix: PropTypes.Requireable<string>;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export { IdPrefix };
|
|
@@ -347,9 +347,6 @@ const MenuItemRadioGroup = /*#__PURE__*/forwardRef(function MenuItemRadioGroup(_
|
|
|
347
347
|
});
|
|
348
348
|
function handleClick(item, e) {
|
|
349
349
|
setSelection(item);
|
|
350
|
-
if (onChange) {
|
|
351
|
-
onChange(e);
|
|
352
|
-
}
|
|
353
350
|
}
|
|
354
351
|
useEffect(() => {
|
|
355
352
|
if (!context.state.hasIcons) {
|
|
@@ -374,7 +371,7 @@ const MenuItemRadioGroup = /*#__PURE__*/forwardRef(function MenuItemRadioGroup(_
|
|
|
374
371
|
"aria-checked": item === selection,
|
|
375
372
|
renderIcon: item === selection ? Checkmark : undefined,
|
|
376
373
|
onClick: e => {
|
|
377
|
-
handleClick(item
|
|
374
|
+
handleClick(item);
|
|
378
375
|
}
|
|
379
376
|
}))));
|
|
380
377
|
});
|
|
@@ -39,6 +39,10 @@ export interface MenuButtonProps extends ComponentProps<'div'> {
|
|
|
39
39
|
* Specify the tabIndex of the button.
|
|
40
40
|
*/
|
|
41
41
|
tabIndex?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Specify a DOM node where the Menu should be rendered in. Defaults to document.body.
|
|
44
|
+
*/
|
|
45
|
+
menuTarget?: Element;
|
|
42
46
|
}
|
|
43
47
|
declare const MenuButton: React.ForwardRefExoticComponent<Omit<MenuButtonProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
44
48
|
export { MenuButton };
|
|
@@ -18,6 +18,7 @@ import { useAttachedMenu } from '../../internal/useAttachedMenu.js';
|
|
|
18
18
|
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
|
+
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
21
22
|
import mergeRefs from '../../tools/mergeRefs.js';
|
|
22
23
|
|
|
23
24
|
const validButtonKinds = ['primary', 'tertiary', 'ghost'];
|
|
@@ -32,14 +33,21 @@ const MenuButton = /*#__PURE__*/forwardRef(function MenuButton(_ref, forwardRef)
|
|
|
32
33
|
size: size$1 = 'lg',
|
|
33
34
|
menuAlignment = 'bottom',
|
|
34
35
|
tabIndex = 0,
|
|
36
|
+
menuTarget,
|
|
35
37
|
...rest
|
|
36
38
|
} = _ref;
|
|
39
|
+
// feature flag utilized to separate out only the dynamic styles from @floating-ui
|
|
40
|
+
// flag is turned on when collision detection (ie. flip, hide) logic is not desired
|
|
41
|
+
const enableOnlyFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles');
|
|
37
42
|
const id = useId('MenuButton');
|
|
38
43
|
const prefix = usePrefix();
|
|
39
44
|
const triggerRef = useRef(null);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
let middlewares = [];
|
|
46
|
+
if (!enableOnlyFloatingStyles) {
|
|
47
|
+
middlewares = [flip({
|
|
48
|
+
crossAxis: false
|
|
49
|
+
})];
|
|
50
|
+
}
|
|
43
51
|
if (menuAlignment === 'bottom' || menuAlignment === 'top') {
|
|
44
52
|
middlewares.push(size({
|
|
45
53
|
apply(_ref2) {
|
|
@@ -121,7 +129,8 @@ const MenuButton = /*#__PURE__*/forwardRef(function MenuButton(_ref, forwardRef)
|
|
|
121
129
|
mode: "basic",
|
|
122
130
|
size: size$1,
|
|
123
131
|
open: open,
|
|
124
|
-
onClose: handleClose
|
|
132
|
+
onClose: handleClose,
|
|
133
|
+
target: menuTarget
|
|
125
134
|
}, children));
|
|
126
135
|
});
|
|
127
136
|
MenuButton.propTypes = {
|
|
@@ -160,7 +169,12 @@ MenuButton.propTypes = {
|
|
|
160
169
|
* Specify the tabIndex of the button.
|
|
161
170
|
*/
|
|
162
171
|
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
|
|
163
|
-
tabIndex: PropTypes.number
|
|
172
|
+
tabIndex: PropTypes.number,
|
|
173
|
+
/**
|
|
174
|
+
* Specify a DOM node where the Menu should be rendered in. Defaults to document.body.
|
|
175
|
+
*/
|
|
176
|
+
|
|
177
|
+
menuTarget: PropTypes.instanceOf(typeof Element !== 'undefined' ? Element : Object)
|
|
164
178
|
};
|
|
165
179
|
|
|
166
180
|
export { MenuButton };
|
|
@@ -27,6 +27,7 @@ import '../Checkbox/Checkbox.Skeleton.js';
|
|
|
27
27
|
import { noopFn } from '../../internal/noopFn.js';
|
|
28
28
|
import { useFloating, flip, size, autoUpdate } from '@floating-ui/react';
|
|
29
29
|
import { hide } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs.js';
|
|
30
|
+
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
30
31
|
import { match } from '../../internal/keyboard/match.js';
|
|
31
32
|
import { ListBoxSize } from '../ListBox/ListBoxPropTypes.js';
|
|
32
33
|
import { Delete, Escape, Space, ArrowDown, Enter } from '../../internal/keyboard/keys.js';
|
|
@@ -125,11 +126,12 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
125
126
|
const [prevOpenProp, setPrevOpenProp] = useState(open);
|
|
126
127
|
const [topItems, setTopItems] = useState([]);
|
|
127
128
|
const [itemsCleared, setItemsCleared] = useState(false);
|
|
129
|
+
const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
|
|
128
130
|
const {
|
|
129
131
|
refs,
|
|
130
132
|
floatingStyles,
|
|
131
133
|
middlewareData
|
|
132
|
-
} = useFloating(
|
|
134
|
+
} = useFloating(enableFloatingStyles ? {
|
|
133
135
|
placement: direction,
|
|
134
136
|
// The floating element is positioned relative to its nearest
|
|
135
137
|
// containing block (usually the viewport). It will in many cases also
|
|
@@ -137,7 +139,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
137
139
|
// https://floating-ui.com/docs/misc#clipping
|
|
138
140
|
strategy: 'fixed',
|
|
139
141
|
// Middleware order matters, arrow should be last
|
|
140
|
-
middleware: [flip({
|
|
142
|
+
middleware: [autoAlign && flip({
|
|
141
143
|
crossAxis: false
|
|
142
144
|
}), size({
|
|
143
145
|
apply(_ref2) {
|
|
@@ -149,11 +151,11 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
149
151
|
width: `${rects.reference.width}px`
|
|
150
152
|
});
|
|
151
153
|
}
|
|
152
|
-
}), hide()],
|
|
154
|
+
}), autoAlign && hide()],
|
|
153
155
|
whileElementsMounted: autoUpdate
|
|
154
156
|
} : {});
|
|
155
157
|
useLayoutEffect(() => {
|
|
156
|
-
if (
|
|
158
|
+
if (enableFloatingStyles) {
|
|
157
159
|
const updatedFloatingStyles = {
|
|
158
160
|
...floatingStyles,
|
|
159
161
|
visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
|
|
@@ -164,7 +166,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
164
166
|
}
|
|
165
167
|
});
|
|
166
168
|
}
|
|
167
|
-
}, [
|
|
169
|
+
}, [enableFloatingStyles, floatingStyles, refs.floating, middlewareData, open]);
|
|
168
170
|
const {
|
|
169
171
|
selectedItems: controlledSelectedItems,
|
|
170
172
|
onItemChange,
|
|
@@ -279,7 +281,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
279
281
|
[`${prefix}--multi-select--selected`]: selectedItems && selectedItems.length > 0,
|
|
280
282
|
[`${prefix}--list-box--up`]: direction === 'top',
|
|
281
283
|
[`${prefix}--multi-select--readonly`]: readOnly,
|
|
282
|
-
[`${prefix}--autoalign`]:
|
|
284
|
+
[`${prefix}--autoalign`]: enableFloatingStyles,
|
|
283
285
|
[`${prefix}--multi-select--selectall`]: selectAll
|
|
284
286
|
});
|
|
285
287
|
|
|
@@ -410,8 +412,8 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
410
412
|
|
|
411
413
|
// Memoize the value of getMenuProps to avoid an infinite loop
|
|
412
414
|
const menuProps = useMemo(() => getMenuProps({
|
|
413
|
-
ref:
|
|
414
|
-
}), [
|
|
415
|
+
ref: enableFloatingStyles ? refs.setFloating : null
|
|
416
|
+
}), [enableFloatingStyles, getMenuProps, refs.setFloating]);
|
|
415
417
|
return /*#__PURE__*/React__default.createElement("div", {
|
|
416
418
|
className: wrapperClasses
|
|
417
419
|
}, /*#__PURE__*/React__default.createElement("label", _extends({
|
|
@@ -438,7 +440,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
438
440
|
className: `${prefix}--list-box__invalid-icon ${prefix}--list-box__invalid-icon--warning`
|
|
439
441
|
}), /*#__PURE__*/React__default.createElement("div", {
|
|
440
442
|
className: multiSelectFieldWrapperClasses,
|
|
441
|
-
ref:
|
|
443
|
+
ref: enableFloatingStyles ? refs.setReference : null
|
|
442
444
|
}, selectedItems.length > 0 && /*#__PURE__*/React__default.createElement(ListBox.Selection, {
|
|
443
445
|
readOnly: readOnly,
|
|
444
446
|
clearSelection: !disabled && !readOnly ? clearSelection : noopFn,
|
|
@@ -38,6 +38,10 @@ interface OverflowMenuProps {
|
|
|
38
38
|
* Specify how the trigger tooltip should be aligned.
|
|
39
39
|
*/
|
|
40
40
|
tooltipAlignment?: 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'left' | 'right';
|
|
41
|
+
/**
|
|
42
|
+
* Specify a DOM node where the Menu should be rendered in. Defaults to document.body.
|
|
43
|
+
*/
|
|
44
|
+
menuTarget?: Element;
|
|
41
45
|
}
|
|
42
46
|
declare const OverflowMenu: React.ForwardRefExoticComponent<OverflowMenuProps & React.RefAttributes<HTMLDivElement>>;
|
|
43
47
|
export { OverflowMenu };
|
|
@@ -11,6 +11,7 @@ import PropTypes from 'prop-types';
|
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { OverflowMenuVertical } from '@carbon/icons-react';
|
|
13
13
|
import { useFloating, flip, autoUpdate } from '@floating-ui/react';
|
|
14
|
+
import { useFeatureFlag } from '../../FeatureFlags/index.js';
|
|
14
15
|
import { IconButton } from '../../IconButton/index.js';
|
|
15
16
|
import { Menu } from '../../Menu/Menu.js';
|
|
16
17
|
import '../../Menu/MenuItem.js';
|
|
@@ -30,14 +31,16 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
30
31
|
size = defaultSize,
|
|
31
32
|
menuAlignment = 'bottom-start',
|
|
32
33
|
tooltipAlignment,
|
|
34
|
+
menuTarget,
|
|
33
35
|
...rest
|
|
34
36
|
} = _ref;
|
|
37
|
+
const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
|
|
35
38
|
const {
|
|
36
39
|
refs,
|
|
37
40
|
floatingStyles,
|
|
38
41
|
placement,
|
|
39
42
|
middlewareData
|
|
40
|
-
} = useFloating(
|
|
43
|
+
} = useFloating(enableFloatingStyles ? {
|
|
41
44
|
// Computing the position starts with initial positioning
|
|
42
45
|
// via `placement`.
|
|
43
46
|
placement: menuAlignment,
|
|
@@ -49,14 +52,16 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
49
52
|
// Middleware are executed as an in-between “middle” step of the
|
|
50
53
|
// initial `placement` computation and eventual return of data for
|
|
51
54
|
// rendering. Each middleware is executed in order.
|
|
52
|
-
middleware: [flip({
|
|
55
|
+
middleware: [autoAlign && flip({
|
|
53
56
|
// An explicit array of placements to try if the initial
|
|
54
57
|
// `placement` doesn’t fit on the axes in which overflow
|
|
55
58
|
// is checked.
|
|
56
59
|
fallbackPlacements: menuAlignment.includes('bottom') ? ['bottom-start', 'bottom-end', 'top-start', 'top-end'] : ['top-start', 'top-end', 'bottom-start', 'bottom-end']
|
|
57
60
|
})],
|
|
58
61
|
whileElementsMounted: autoUpdate
|
|
59
|
-
} : {}
|
|
62
|
+
} : {}
|
|
63
|
+
// When autoAlign is turned off & the `enable-v12-dynamic-floating-styles` feature flag is not
|
|
64
|
+
// enabled, floating-ui will not be used
|
|
60
65
|
);
|
|
61
66
|
const id = useId('overflowmenu');
|
|
62
67
|
const prefix = usePrefix();
|
|
@@ -70,21 +75,21 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
70
75
|
handleClose
|
|
71
76
|
} = useAttachedMenu(triggerRef);
|
|
72
77
|
useEffect(() => {
|
|
73
|
-
if (
|
|
78
|
+
if (enableFloatingStyles) {
|
|
74
79
|
Object.keys(floatingStyles).forEach(style => {
|
|
75
80
|
if (refs.floating.current) {
|
|
76
81
|
refs.floating.current.style[style] = floatingStyles[style];
|
|
77
82
|
}
|
|
78
83
|
});
|
|
79
84
|
}
|
|
80
|
-
}, [floatingStyles,
|
|
85
|
+
}, [floatingStyles, enableFloatingStyles, refs.floating, open, placement, middlewareData]);
|
|
81
86
|
function handleTriggerClick() {
|
|
82
87
|
if (triggerRef.current) {
|
|
83
88
|
hookOnClick();
|
|
84
89
|
}
|
|
85
90
|
}
|
|
86
91
|
const containerClasses = cx(className, `${prefix}--overflow-menu__container`, {
|
|
87
|
-
[`${prefix}--autoalign`]:
|
|
92
|
+
[`${prefix}--autoalign`]: enableFloatingStyles
|
|
88
93
|
});
|
|
89
94
|
const menuClasses = cx(`${prefix}--overflow-menu__${menuAlignment}`);
|
|
90
95
|
const triggerClasses = cx(`${prefix}--overflow-menu`, {
|
|
@@ -115,12 +120,13 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
115
120
|
className: menuClasses,
|
|
116
121
|
id: id,
|
|
117
122
|
size: size,
|
|
118
|
-
legacyAutoalign: !
|
|
123
|
+
legacyAutoalign: !enableFloatingStyles,
|
|
119
124
|
open: open,
|
|
120
125
|
onClose: handleClose,
|
|
121
126
|
x: x,
|
|
122
127
|
y: y,
|
|
123
|
-
label: label
|
|
128
|
+
label: label,
|
|
129
|
+
target: menuTarget
|
|
124
130
|
}, children));
|
|
125
131
|
});
|
|
126
132
|
OverflowMenu.propTypes = {
|
|
@@ -156,7 +162,11 @@ OverflowMenu.propTypes = {
|
|
|
156
162
|
/**
|
|
157
163
|
* Specify how the trigger tooltip should be aligned.
|
|
158
164
|
*/
|
|
159
|
-
tooltipAlignment: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'right'])
|
|
165
|
+
tooltipAlignment: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'right']),
|
|
166
|
+
/**
|
|
167
|
+
* Specify a DOM node where the Menu should be rendered in. Defaults to document.body.
|
|
168
|
+
*/
|
|
169
|
+
menuTarget: PropTypes.instanceOf(typeof Element !== 'undefined' ? Element : Object)
|
|
160
170
|
};
|
|
161
171
|
|
|
162
172
|
export { OverflowMenu };
|
|
@@ -213,7 +213,7 @@ const PaginationNav = /*#__PURE__*/React__default.forwardRef(function Pagination
|
|
|
213
213
|
}
|
|
214
214
|
function pageWouldBeHidden(page) {
|
|
215
215
|
const startOffset = itemsDisplayedOnPage <= 4 && page > 1 ? 0 : 1;
|
|
216
|
-
const wouldBeHiddenInFront = page >= startOffset && page <= cuts.front;
|
|
216
|
+
const wouldBeHiddenInFront = page >= startOffset && page <= cuts.front || page === 0;
|
|
217
217
|
const wouldBeHiddenInBack = page >= totalItems - cuts.back - 1 && page <= totalItems - 2;
|
|
218
218
|
return wouldBeHiddenInFront || wouldBeHiddenInBack;
|
|
219
219
|
}
|