@carbon/react 1.60.2 → 1.61.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 +972 -1013
- package/es/components/ComboBox/ComboBox.js +8 -8
- package/es/components/ComposedModal/ComposedModal.js +4 -2
- package/es/components/DatePicker/DatePicker.js +6 -1
- package/es/components/Dropdown/Dropdown.d.ts +4 -0
- package/es/components/Dropdown/Dropdown.js +53 -8
- package/es/components/Modal/Modal.js +4 -2
- package/es/components/MultiSelect/FilterableMultiSelect.d.ts +20 -14
- package/es/components/MultiSelect/FilterableMultiSelect.js +59 -8
- package/es/components/MultiSelect/MultiSelect.d.ts +7 -38
- package/es/components/MultiSelect/MultiSelect.js +52 -5
- package/es/components/MultiSelect/MultiSelectPropTypes.d.ts +19 -16
- package/es/components/OverflowMenu/OverflowMenu.js +0 -1
- package/es/components/OverflowMenu/next/index.d.ts +4 -0
- package/es/components/OverflowMenu/next/index.js +41 -2
- package/es/components/UIShell/HeaderContainer.d.ts +11 -9
- package/es/components/UIShell/HeaderContainer.js +9 -7
- package/lib/components/ComboBox/ComboBox.js +7 -7
- package/lib/components/ComposedModal/ComposedModal.js +6 -4
- package/lib/components/DatePicker/DatePicker.js +6 -1
- package/lib/components/Dropdown/Dropdown.d.ts +4 -0
- package/lib/components/Dropdown/Dropdown.js +49 -4
- package/lib/components/Modal/Modal.js +6 -4
- package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +20 -14
- package/lib/components/MultiSelect/FilterableMultiSelect.js +56 -5
- package/lib/components/MultiSelect/MultiSelect.d.ts +7 -38
- package/lib/components/MultiSelect/MultiSelect.js +49 -2
- package/lib/components/MultiSelect/MultiSelectPropTypes.d.ts +19 -16
- package/lib/components/OverflowMenu/OverflowMenu.js +0 -1
- package/lib/components/OverflowMenu/next/index.d.ts +4 -0
- package/lib/components/OverflowMenu/next/index.js +40 -1
- package/lib/components/UIShell/HeaderContainer.d.ts +11 -9
- package/lib/components/UIShell/HeaderContainer.js +9 -7
- package/package.json +7 -7
|
@@ -11,7 +11,7 @@ import cx from 'classnames';
|
|
|
11
11
|
import { useSelect } from 'downshift';
|
|
12
12
|
import isEqual from 'lodash.isequal';
|
|
13
13
|
import PropTypes from 'prop-types';
|
|
14
|
-
import React__default, { useContext, useRef, useState, useMemo } from 'react';
|
|
14
|
+
import React__default, { useContext, useRef, useState, useLayoutEffect, useMemo } 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';
|
|
@@ -23,6 +23,7 @@ import { usePrefix } from '../../internal/usePrefix.js';
|
|
|
23
23
|
import '../FluidForm/FluidForm.js';
|
|
24
24
|
import { FormContext } from '../FluidForm/FormContext.js';
|
|
25
25
|
import { noopFn } from '../../internal/noopFn.js';
|
|
26
|
+
import { useFloating, flip, size, autoUpdate } from '@floating-ui/react';
|
|
26
27
|
import { match } from '../../internal/keyboard/match.js';
|
|
27
28
|
import { ListBoxSize } from '../ListBox/ListBoxPropTypes.js';
|
|
28
29
|
import { Delete, Escape, Space, ArrowDown, Enter } from '../../internal/keyboard/keys.js';
|
|
@@ -57,6 +58,7 @@ const defaultItemToString = item => {
|
|
|
57
58
|
};
|
|
58
59
|
const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
59
60
|
let {
|
|
61
|
+
autoAlign = false,
|
|
60
62
|
className: containerClassName,
|
|
61
63
|
id,
|
|
62
64
|
items,
|
|
@@ -67,7 +69,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
67
69
|
helperText,
|
|
68
70
|
label,
|
|
69
71
|
type = 'default',
|
|
70
|
-
size,
|
|
72
|
+
size: size$1,
|
|
71
73
|
disabled = false,
|
|
72
74
|
initialSelectedItems = [],
|
|
73
75
|
sortItems = defaultSortItems,
|
|
@@ -116,6 +118,42 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
116
118
|
onChange,
|
|
117
119
|
selectedItems: selected
|
|
118
120
|
});
|
|
121
|
+
const {
|
|
122
|
+
refs,
|
|
123
|
+
floatingStyles,
|
|
124
|
+
middlewareData
|
|
125
|
+
} = useFloating(autoAlign ? {
|
|
126
|
+
placement: direction,
|
|
127
|
+
// The floating element is positioned relative to its nearest
|
|
128
|
+
// containing block (usually the viewport). It will in many cases also
|
|
129
|
+
// “break” the floating element out of a clipping ancestor.
|
|
130
|
+
// https://floating-ui.com/docs/misc#clipping
|
|
131
|
+
strategy: 'fixed',
|
|
132
|
+
// Middleware order matters, arrow should be last
|
|
133
|
+
middleware: [flip({
|
|
134
|
+
crossAxis: false
|
|
135
|
+
}), size({
|
|
136
|
+
apply(_ref2) {
|
|
137
|
+
let {
|
|
138
|
+
rects,
|
|
139
|
+
elements
|
|
140
|
+
} = _ref2;
|
|
141
|
+
Object.assign(elements.floating.style, {
|
|
142
|
+
width: `${rects.reference.width}px`
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
})],
|
|
146
|
+
whileElementsMounted: autoUpdate
|
|
147
|
+
} : {});
|
|
148
|
+
useLayoutEffect(() => {
|
|
149
|
+
if (autoAlign) {
|
|
150
|
+
Object.keys(floatingStyles).forEach(style => {
|
|
151
|
+
if (refs.floating.current) {
|
|
152
|
+
refs.floating.current.style[style] = floatingStyles[style];
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}, [autoAlign, floatingStyles, refs.floating, middlewareData, open]);
|
|
119
157
|
|
|
120
158
|
// Filter out items with an object having undefined values
|
|
121
159
|
const filteredItems = useMemo(() => {
|
|
@@ -367,7 +405,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
367
405
|
onFocus: isFluid ? handleFocus : undefined,
|
|
368
406
|
onBlur: isFluid ? handleFocus : undefined,
|
|
369
407
|
type: type,
|
|
370
|
-
size: size,
|
|
408
|
+
size: size$1,
|
|
371
409
|
className: className,
|
|
372
410
|
disabled: disabled,
|
|
373
411
|
light: light,
|
|
@@ -382,7 +420,8 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
382
420
|
}), showWarning && /*#__PURE__*/React__default.createElement(WarningAltFilled, {
|
|
383
421
|
className: `${prefix}--list-box__invalid-icon ${prefix}--list-box__invalid-icon--warning`
|
|
384
422
|
}), /*#__PURE__*/React__default.createElement("div", {
|
|
385
|
-
className: multiSelectFieldWrapperClasses
|
|
423
|
+
className: multiSelectFieldWrapperClasses,
|
|
424
|
+
ref: refs.setReference
|
|
386
425
|
}, selectedItems.length > 0 && /*#__PURE__*/React__default.createElement(ListBox.Selection, {
|
|
387
426
|
readOnly: readOnly,
|
|
388
427
|
clearSelection: !disabled && !readOnly ? clearSelection : noopFn,
|
|
@@ -405,7 +444,9 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
405
444
|
}, label), /*#__PURE__*/React__default.createElement(ListBox.MenuIcon, {
|
|
406
445
|
isOpen: isOpen,
|
|
407
446
|
translateWithId: translateWithId
|
|
408
|
-
})), normalizedSlug), /*#__PURE__*/React__default.createElement(ListBox.Menu, getMenuProps(
|
|
447
|
+
})), normalizedSlug), /*#__PURE__*/React__default.createElement(ListBox.Menu, getMenuProps({
|
|
448
|
+
ref: refs.setFloating
|
|
449
|
+
}), isOpen &&
|
|
409
450
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
410
451
|
sortItems(filteredItems, sortOptions).map((item, index) => {
|
|
411
452
|
const isChecked = selectedItems.filter(selected => isEqual(selected, item)).length > 0;
|
|
@@ -444,6 +485,12 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
444
485
|
MultiSelect.displayName = 'MultiSelect';
|
|
445
486
|
MultiSelect.propTypes = {
|
|
446
487
|
...sortingPropTypes,
|
|
488
|
+
/**
|
|
489
|
+
* **Experimental**: Will attempt to automatically align the floating
|
|
490
|
+
* element to avoid collisions with the viewport and being clipped by
|
|
491
|
+
* ancestor elements.
|
|
492
|
+
*/
|
|
493
|
+
autoAlign: PropTypes.bool,
|
|
447
494
|
/**
|
|
448
495
|
* Provide a custom class name to be added to the outermost node in the
|
|
449
496
|
* component
|
|
@@ -34,29 +34,32 @@ export declare const sortingPropTypes: {
|
|
|
34
34
|
*/
|
|
35
35
|
sortItems: PropTypes.Requireable<(...args: any[]) => any>;
|
|
36
36
|
};
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
interface DownshiftTypedProps<ItemType> {
|
|
38
|
+
itemToString?(item: ItemType): string;
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
interface SharedOptions {
|
|
41
|
+
locale: string;
|
|
42
|
+
}
|
|
43
|
+
export interface SortItemsOptions<ItemType> extends SharedOptions, DownshiftTypedProps<ItemType> {
|
|
44
|
+
compareItems(item1: ItemType, item2: ItemType, options: SharedOptions): number;
|
|
45
|
+
selectedItems: ItemType[];
|
|
46
|
+
}
|
|
47
|
+
export interface MultiSelectSortingProps<ItemType> {
|
|
41
48
|
/**
|
|
42
|
-
* Provide a compare function that is used
|
|
43
|
-
*
|
|
49
|
+
* Provide a compare function that is used to determine the ordering of
|
|
50
|
+
* options. See 'sortItems' for more control.
|
|
44
51
|
*/
|
|
45
|
-
compareItems(
|
|
46
|
-
locale: string;
|
|
47
|
-
}): number;
|
|
52
|
+
compareItems?(item1: ItemType, item2: ItemType, options: SharedOptions): number;
|
|
48
53
|
/**
|
|
49
54
|
* Provide a method that sorts all options in the control. Overriding this
|
|
50
55
|
* prop means that you also have to handle the sort logic for selected versus
|
|
51
56
|
* un-selected items. If you just want to control ordering, consider the
|
|
52
57
|
* `compareItems` prop instead.
|
|
58
|
+
*
|
|
59
|
+
* The return value should be a number whose sign indicates the relative order
|
|
60
|
+
* of the two elements: negative if a is less than b, positive if a is greater
|
|
61
|
+
* than b, and zero if they are equal.
|
|
53
62
|
*/
|
|
54
|
-
sortItems(items:
|
|
55
|
-
selectedItems: Item[];
|
|
56
|
-
itemToString(item: Item): string;
|
|
57
|
-
compareItems(itemA: string, itemB: string, ctx: {
|
|
58
|
-
locale: string;
|
|
59
|
-
}): number;
|
|
60
|
-
locale: string;
|
|
61
|
-
}): Item[];
|
|
63
|
+
sortItems?(items: ReadonlyArray<ItemType>, options: SortItemsOptions<ItemType>): ItemType[];
|
|
62
64
|
}
|
|
65
|
+
export {};
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React, { type ComponentType, type FunctionComponent } from 'react';
|
|
8
8
|
interface OverflowMenuProps {
|
|
9
|
+
/**
|
|
10
|
+
* **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
|
|
11
|
+
*/
|
|
12
|
+
autoAlign?: boolean;
|
|
9
13
|
/**
|
|
10
14
|
* A collection of MenuItems to be rendered within this OverflowMenu.
|
|
11
15
|
*/
|
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
-
import React__default, { useRef } from 'react';
|
|
9
|
+
import React__default, { useRef, useEffect } from 'react';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { OverflowMenuVertical } from '@carbon/icons-react';
|
|
13
|
+
import { useFloating, flip, autoUpdate } from '@floating-ui/react';
|
|
13
14
|
import { IconButton } from '../../IconButton/index.js';
|
|
14
15
|
import { Menu } from '../../Menu/Menu.js';
|
|
15
16
|
import '../../Menu/MenuItem.js';
|
|
17
|
+
import mergeRefs from '../../../tools/mergeRefs.js';
|
|
16
18
|
import { useId } from '../../../internal/useId.js';
|
|
17
19
|
import { usePrefix } from '../../../internal/usePrefix.js';
|
|
18
20
|
import { useAttachedMenu } from '../../../internal/useAttachedMenu.js';
|
|
@@ -20,6 +22,7 @@ import { useAttachedMenu } from '../../../internal/useAttachedMenu.js';
|
|
|
20
22
|
const defaultSize = 'md';
|
|
21
23
|
const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMenu(_ref, forwardRef) {
|
|
22
24
|
let {
|
|
25
|
+
autoAlign = false,
|
|
23
26
|
children,
|
|
24
27
|
className,
|
|
25
28
|
label = 'Options',
|
|
@@ -29,6 +32,26 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
29
32
|
tooltipAlignment,
|
|
30
33
|
...rest
|
|
31
34
|
} = _ref;
|
|
35
|
+
const {
|
|
36
|
+
refs,
|
|
37
|
+
floatingStyles,
|
|
38
|
+
placement,
|
|
39
|
+
middlewareData
|
|
40
|
+
} = useFloating(autoAlign ? {
|
|
41
|
+
placement: menuAlignment,
|
|
42
|
+
// The floating element is positioned relative to its nearest
|
|
43
|
+
// containing block (usually the viewport). It will in many cases also
|
|
44
|
+
// “break” the floating element out of a clipping ancestor.
|
|
45
|
+
// https://floating-ui.com/docs/misc#clipping
|
|
46
|
+
strategy: 'fixed',
|
|
47
|
+
// Middleware order matters, arrow should be last
|
|
48
|
+
middleware: [flip({
|
|
49
|
+
fallbackAxisSideDirection: 'start',
|
|
50
|
+
fallbackPlacements: ['top-start', 'top-end', 'bottom-start', 'bottom-end']
|
|
51
|
+
})],
|
|
52
|
+
whileElementsMounted: autoUpdate
|
|
53
|
+
} : {} // When autoAlign is turned off, floating-ui will not be used
|
|
54
|
+
);
|
|
32
55
|
const id = useId('overflowmenu');
|
|
33
56
|
const prefix = usePrefix();
|
|
34
57
|
const triggerRef = useRef(null);
|
|
@@ -40,6 +63,15 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
40
63
|
handleMousedown,
|
|
41
64
|
handleClose
|
|
42
65
|
} = useAttachedMenu(triggerRef);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (autoAlign) {
|
|
68
|
+
Object.keys(floatingStyles).forEach(style => {
|
|
69
|
+
if (refs.floating.current) {
|
|
70
|
+
refs.floating.current.style[style] = floatingStyles[style];
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}, [floatingStyles, autoAlign, refs.floating, open, placement, middlewareData]);
|
|
43
75
|
function handleTriggerClick() {
|
|
44
76
|
if (triggerRef.current) {
|
|
45
77
|
hookOnClick();
|
|
@@ -50,6 +82,7 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
50
82
|
const triggerClasses = cx(`${prefix}--overflow-menu`, {
|
|
51
83
|
[`${prefix}--overflow-menu--open`]: open
|
|
52
84
|
}, size !== defaultSize && `${prefix}--overflow-menu--${size}`);
|
|
85
|
+
const floatingRef = mergeRefs(triggerRef, refs.setReference);
|
|
53
86
|
return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
|
|
54
87
|
className: containerClasses,
|
|
55
88
|
"aria-owns": open ? id : undefined,
|
|
@@ -61,17 +94,19 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
61
94
|
className: triggerClasses,
|
|
62
95
|
onClick: handleTriggerClick,
|
|
63
96
|
onMouseDown: handleMousedown,
|
|
64
|
-
ref:
|
|
97
|
+
ref: floatingRef,
|
|
65
98
|
label: label,
|
|
66
99
|
align: tooltipAlignment
|
|
67
100
|
}, /*#__PURE__*/React__default.createElement(IconElement, {
|
|
68
101
|
className: `${prefix}--overflow-menu__icon`
|
|
69
102
|
})), /*#__PURE__*/React__default.createElement(Menu, {
|
|
70
103
|
containerRef: triggerRef,
|
|
104
|
+
ref: refs.setFloating,
|
|
71
105
|
menuAlignment: menuAlignment,
|
|
72
106
|
className: menuClasses,
|
|
73
107
|
id: id,
|
|
74
108
|
size: size,
|
|
109
|
+
legacyAutoalign: !autoAlign,
|
|
75
110
|
open: open,
|
|
76
111
|
onClose: handleClose,
|
|
77
112
|
x: x,
|
|
@@ -80,6 +115,10 @@ const OverflowMenu = /*#__PURE__*/React__default.forwardRef(function OverflowMen
|
|
|
80
115
|
}, children));
|
|
81
116
|
});
|
|
82
117
|
OverflowMenu.propTypes = {
|
|
118
|
+
/**
|
|
119
|
+
* **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
|
|
120
|
+
*/
|
|
121
|
+
autoAlign: PropTypes.bool,
|
|
83
122
|
/**
|
|
84
123
|
* A collection of MenuItems to be rendered within this OverflowMenu.
|
|
85
124
|
*/
|
|
@@ -6,15 +6,17 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import React from 'react';
|
|
9
|
-
interface HeaderContainerRenderProps {
|
|
9
|
+
export interface HeaderContainerRenderProps {
|
|
10
10
|
isSideNavExpanded: boolean;
|
|
11
11
|
onClickSideNavExpand: () => void;
|
|
12
12
|
}
|
|
13
|
-
export
|
|
13
|
+
export type HeaderContainerProps<P extends HeaderContainerRenderProps> = {
|
|
14
14
|
isSideNavExpanded?: boolean;
|
|
15
|
-
render: React.ComponentType<
|
|
16
|
-
}
|
|
17
|
-
|
|
15
|
+
render: React.ComponentType<P>;
|
|
16
|
+
} & {
|
|
17
|
+
[K in keyof Omit<P, keyof HeaderContainerRenderProps>]: P[K];
|
|
18
|
+
};
|
|
19
|
+
declare function HeaderContainer<P extends HeaderContainerRenderProps>({ render: Children, isSideNavExpanded, ...rest }: HeaderContainerProps<P>): import("react/jsx-runtime").JSX.Element;
|
|
18
20
|
declare namespace HeaderContainer {
|
|
19
21
|
var propTypes: {
|
|
20
22
|
/**
|
|
@@ -22,10 +24,10 @@ declare namespace HeaderContainer {
|
|
|
22
24
|
*/
|
|
23
25
|
isSideNavExpanded: PropTypes.Requireable<boolean>;
|
|
24
26
|
/**
|
|
25
|
-
* A function or component that is
|
|
26
|
-
* properties
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* A function or a component that is invoked with `isSideNavExpanded` and `onClickSideNavExpand`.
|
|
28
|
+
* The function or component can then use those properties to within the components it
|
|
29
|
+
* returns, such as with the HeaderMenuButton and SideNav components. Additional props will also be passed
|
|
30
|
+
* into this component for convenience.
|
|
29
31
|
*/
|
|
30
32
|
render: PropTypes.Validator<NonNullable<PropTypes.ReactComponentLike>>;
|
|
31
33
|
};
|
|
@@ -5,6 +5,7 @@
|
|
|
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
10
|
import React__default, { useState, useCallback } from 'react';
|
|
10
11
|
import { useWindowEvent } from '../../internal/useEvent.js';
|
|
@@ -14,7 +15,8 @@ import { Escape } from '../../internal/keyboard/keys.js';
|
|
|
14
15
|
function HeaderContainer(_ref) {
|
|
15
16
|
let {
|
|
16
17
|
render: Children,
|
|
17
|
-
isSideNavExpanded = false
|
|
18
|
+
isSideNavExpanded = false,
|
|
19
|
+
...rest
|
|
18
20
|
} = _ref;
|
|
19
21
|
//state for expandable sidenav
|
|
20
22
|
const [isSideNavExpandedState, setIsSideNavExpandedState] = useState(isSideNavExpanded);
|
|
@@ -26,10 +28,10 @@ function HeaderContainer(_ref) {
|
|
|
26
28
|
const handleHeaderMenuButtonClick = useCallback(() => {
|
|
27
29
|
setIsSideNavExpandedState(prevIsSideNavExpanded => !prevIsSideNavExpanded);
|
|
28
30
|
}, [setIsSideNavExpandedState]);
|
|
29
|
-
return /*#__PURE__*/React__default.createElement(Children, {
|
|
31
|
+
return /*#__PURE__*/React__default.createElement(Children, _extends({}, rest, {
|
|
30
32
|
isSideNavExpanded: isSideNavExpandedState,
|
|
31
33
|
onClickSideNavExpand: handleHeaderMenuButtonClick
|
|
32
|
-
});
|
|
34
|
+
}));
|
|
33
35
|
}
|
|
34
36
|
HeaderContainer.propTypes = {
|
|
35
37
|
/**
|
|
@@ -37,10 +39,10 @@ HeaderContainer.propTypes = {
|
|
|
37
39
|
*/
|
|
38
40
|
isSideNavExpanded: PropTypes.bool,
|
|
39
41
|
/**
|
|
40
|
-
* A function or component that is
|
|
41
|
-
* properties
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* A function or a component that is invoked with `isSideNavExpanded` and `onClickSideNavExpand`.
|
|
43
|
+
* The function or component can then use those properties to within the components it
|
|
44
|
+
* returns, such as with the HeaderMenuButton and SideNav components. Additional props will also be passed
|
|
45
|
+
* into this component for convenience.
|
|
44
46
|
*/
|
|
45
47
|
render: PropTypes.elementType.isRequired
|
|
46
48
|
};
|
|
@@ -392,6 +392,10 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
392
392
|
// when both the message is supplied *and* when the component is in
|
|
393
393
|
// the matching state (invalid, warn, etc).
|
|
394
394
|
const ariaDescribedBy = invalid && invalidText && invalidTextId || warn && warnText && warnTextId || helperText && !isFluid && helperTextId || undefined;
|
|
395
|
+
const menuProps = React.useMemo(() => getMenuProps({
|
|
396
|
+
'aria-label': deprecatedAriaLabel || ariaLabel,
|
|
397
|
+
ref: autoAlign ? refs.setFloating : null
|
|
398
|
+
}), [autoAlign, deprecatedAriaLabel, ariaLabel]);
|
|
395
399
|
return /*#__PURE__*/React__default["default"].createElement("div", {
|
|
396
400
|
className: wrapperClasses
|
|
397
401
|
}, titleText && /*#__PURE__*/React__default["default"].createElement(Text.Text, _rollupPluginBabelHelpers["extends"]({
|
|
@@ -409,7 +413,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
409
413
|
light: light,
|
|
410
414
|
size: size,
|
|
411
415
|
warn: warn,
|
|
412
|
-
ref: refs.setReference,
|
|
416
|
+
ref: autoAlign ? refs.setReference : null,
|
|
413
417
|
warnText: warnText,
|
|
414
418
|
warnTextId: warnTextId
|
|
415
419
|
}, /*#__PURE__*/React__default["default"].createElement("div", {
|
|
@@ -422,7 +426,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
422
426
|
"aria-haspopup": "listbox",
|
|
423
427
|
title: textInput?.current?.value
|
|
424
428
|
}, getInputProps({
|
|
425
|
-
'aria-controls': isOpen ? undefined :
|
|
429
|
+
'aria-controls': isOpen ? undefined : menuProps.id,
|
|
426
430
|
placeholder,
|
|
427
431
|
ref: {
|
|
428
432
|
...mergeRefs["default"](textInput, ref)
|
|
@@ -484,11 +488,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
484
488
|
// @ts-expect-error
|
|
485
489
|
isOpen: isOpen,
|
|
486
490
|
translateWithId: translateWithId
|
|
487
|
-
}))), normalizedSlug, /*#__PURE__*/React__default["default"].createElement(index["default"].Menu,
|
|
488
|
-
'aria-label': deprecatedAriaLabel || ariaLabel
|
|
489
|
-
}), {
|
|
490
|
-
ref: mergeRefs["default"](getMenuProps().ref, refs.setFloating)
|
|
491
|
-
}), isOpen ? filterItems(items, itemToString, inputValue).map((item, index$1) => {
|
|
491
|
+
}))), normalizedSlug, /*#__PURE__*/React__default["default"].createElement(index["default"].Menu, menuProps, isOpen ? filterItems(items, itemToString, inputValue).map((item, index$1) => {
|
|
492
492
|
const isObject = item !== null && typeof item === 'object';
|
|
493
493
|
const title = isObject && 'text' in item && itemToElement ? item.text?.toString() : itemToString(item);
|
|
494
494
|
const itemProps = getItemProps({
|
|
@@ -13,6 +13,7 @@ var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelper
|
|
|
13
13
|
var React = require('react');
|
|
14
14
|
var reactIs = require('react-is');
|
|
15
15
|
var PropTypes = require('prop-types');
|
|
16
|
+
var index = require('../Layer/index.js');
|
|
16
17
|
var ModalHeader = require('./ModalHeader.js');
|
|
17
18
|
var ModalFooter = require('./ModalFooter.js');
|
|
18
19
|
var debounce = require('lodash.debounce');
|
|
@@ -23,7 +24,7 @@ var toggleClass = require('../../tools/toggleClass.js');
|
|
|
23
24
|
var requiredIfGivenPropIsTruthy = require('../../prop-types/requiredIfGivenPropIsTruthy.js');
|
|
24
25
|
var wrapFocus = require('../../internal/wrapFocus.js');
|
|
25
26
|
var usePrefix = require('../../internal/usePrefix.js');
|
|
26
|
-
var index = require('../FeatureFlags/index.js');
|
|
27
|
+
var index$1 = require('../FeatureFlags/index.js');
|
|
27
28
|
var match = require('../../internal/keyboard/match.js');
|
|
28
29
|
var keys = require('../../internal/keyboard/keys.js');
|
|
29
30
|
|
|
@@ -70,7 +71,7 @@ const ModalBody = /*#__PURE__*/React__default["default"].forwardRef(function Mod
|
|
|
70
71
|
tabIndex: 0,
|
|
71
72
|
role: 'region'
|
|
72
73
|
} : {};
|
|
73
|
-
return /*#__PURE__*/React__default["default"].createElement(
|
|
74
|
+
return /*#__PURE__*/React__default["default"].createElement(index.Layer, _rollupPluginBabelHelpers["extends"]({
|
|
74
75
|
className: contentClass
|
|
75
76
|
}, hasScrollingContentProps, rest, {
|
|
76
77
|
ref: mergeRefs["default"](contentRef, ref)
|
|
@@ -126,7 +127,7 @@ const ComposedModal = /*#__PURE__*/React__default["default"].forwardRef(function
|
|
|
126
127
|
const button = React.useRef(null);
|
|
127
128
|
const startSentinel = React.useRef(null);
|
|
128
129
|
const endSentinel = React.useRef(null);
|
|
129
|
-
const focusTrapWithoutSentinels = index.useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
|
|
130
|
+
const focusTrapWithoutSentinels = index$1.useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
|
|
130
131
|
|
|
131
132
|
// Keep track of modal open/close state
|
|
132
133
|
// and propagate it to the document.body
|
|
@@ -260,7 +261,8 @@ const ComposedModal = /*#__PURE__*/React__default["default"].forwardRef(function
|
|
|
260
261
|
size: 'sm'
|
|
261
262
|
});
|
|
262
263
|
}
|
|
263
|
-
return /*#__PURE__*/React__default["default"].createElement(
|
|
264
|
+
return /*#__PURE__*/React__default["default"].createElement(index.Layer, _rollupPluginBabelHelpers["extends"]({}, rest, {
|
|
265
|
+
level: 0,
|
|
264
266
|
role: "presentation",
|
|
265
267
|
ref: ref,
|
|
266
268
|
"aria-hidden": !open,
|
|
@@ -188,6 +188,8 @@ const DatePicker = /*#__PURE__*/React__default["default"].forwardRef(function Da
|
|
|
188
188
|
|
|
189
189
|
// fix datepicker deleting the selectedDate when the calendar closes
|
|
190
190
|
const onCalendarClose = (selectedDates, dateStr) => {
|
|
191
|
+
endInputField?.current?.focus();
|
|
192
|
+
calendarRef?.current?.calendarContainer?.classList.remove('open');
|
|
191
193
|
setTimeout(() => {
|
|
192
194
|
if (lastStartValue.current && selectedDates[0] && !startInputField.current.value) {
|
|
193
195
|
startInputField.current.value = lastStartValue.current;
|
|
@@ -367,9 +369,12 @@ const DatePicker = /*#__PURE__*/React__default["default"].forwardRef(function Da
|
|
|
367
369
|
calendarRef.current = calendar;
|
|
368
370
|
function handleArrowDown(event) {
|
|
369
371
|
if (match.match(event, keys.Escape)) {
|
|
370
|
-
calendar
|
|
372
|
+
calendar?.calendarContainer?.classList.remove('open');
|
|
371
373
|
}
|
|
372
374
|
if (match.match(event, keys.ArrowDown)) {
|
|
375
|
+
if (event.target == endInputField.current) {
|
|
376
|
+
calendar?.calendarContainer?.classList.add('open');
|
|
377
|
+
}
|
|
373
378
|
const {
|
|
374
379
|
calendarContainer,
|
|
375
380
|
selectedDateElem: fpSelectedDateElem,
|
|
@@ -23,6 +23,10 @@ export interface DropdownProps<ItemType> extends Omit<ReactAttr<HTMLDivElement>,
|
|
|
23
23
|
* Specify a label to be read by screen readers on the container note.
|
|
24
24
|
*/
|
|
25
25
|
ariaLabel?: string;
|
|
26
|
+
/**
|
|
27
|
+
* **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
|
|
28
|
+
*/
|
|
29
|
+
autoAlign?: boolean;
|
|
26
30
|
/**
|
|
27
31
|
* Specify the direction of the dropdown. Can be either top or bottom.
|
|
28
32
|
*/
|
|
@@ -22,6 +22,7 @@ var usePrefix = require('../../internal/usePrefix.js');
|
|
|
22
22
|
require('../FluidForm/FluidForm.js');
|
|
23
23
|
var FormContext = require('../FluidForm/FormContext.js');
|
|
24
24
|
var setupGetInstanceId = require('../../tools/setupGetInstanceId.js');
|
|
25
|
+
var react = require('@floating-ui/react');
|
|
25
26
|
var ListBoxPropTypes = require('../ListBox/ListBoxPropTypes.js');
|
|
26
27
|
|
|
27
28
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -53,6 +54,7 @@ const defaultItemToString = item => {
|
|
|
53
54
|
};
|
|
54
55
|
const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) => {
|
|
55
56
|
let {
|
|
57
|
+
autoAlign = false,
|
|
56
58
|
className: containerClassName,
|
|
57
59
|
disabled = false,
|
|
58
60
|
direction = 'bottom',
|
|
@@ -83,6 +85,40 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
|
|
|
83
85
|
slug,
|
|
84
86
|
...other
|
|
85
87
|
} = _ref;
|
|
88
|
+
const {
|
|
89
|
+
refs,
|
|
90
|
+
floatingStyles
|
|
91
|
+
} = react.useFloating(autoAlign ? {
|
|
92
|
+
placement: direction,
|
|
93
|
+
// The floating element is positioned relative to its nearest
|
|
94
|
+
// containing block (usually the viewport). It will in many cases also
|
|
95
|
+
// “break” the floating element out of a clipping ancestor.
|
|
96
|
+
// https://floating-ui.com/docs/misc#clipping
|
|
97
|
+
strategy: 'fixed',
|
|
98
|
+
// Middleware order matters, arrow should be last
|
|
99
|
+
middleware: [react.size({
|
|
100
|
+
apply(_ref2) {
|
|
101
|
+
let {
|
|
102
|
+
rects,
|
|
103
|
+
elements
|
|
104
|
+
} = _ref2;
|
|
105
|
+
Object.assign(elements.floating.style, {
|
|
106
|
+
width: `${rects.reference.width}px`
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}), react.flip()],
|
|
110
|
+
whileElementsMounted: react.autoUpdate
|
|
111
|
+
} : {} // When autoAlign is turned off, floating-ui will not be used
|
|
112
|
+
);
|
|
113
|
+
React.useEffect(() => {
|
|
114
|
+
if (autoAlign) {
|
|
115
|
+
Object.keys(floatingStyles).forEach(style => {
|
|
116
|
+
if (refs.floating.current) {
|
|
117
|
+
refs.floating.current.style[style] = floatingStyles[style];
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}, [floatingStyles, autoAlign, refs.floating]);
|
|
86
122
|
const prefix = usePrefix.usePrefix();
|
|
87
123
|
const {
|
|
88
124
|
isFluid
|
|
@@ -157,7 +193,8 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
|
|
|
157
193
|
[`${prefix}--dropdown--light`]: light,
|
|
158
194
|
[`${prefix}--dropdown--readonly`]: readOnly,
|
|
159
195
|
[`${prefix}--dropdown--${size}`]: size,
|
|
160
|
-
[`${prefix}--list-box--up`]: direction === 'top'
|
|
196
|
+
[`${prefix}--list-box--up`]: direction === 'top',
|
|
197
|
+
[`${prefix}--dropdown--autoalign`]: autoAlign
|
|
161
198
|
});
|
|
162
199
|
const titleClasses = cx__default["default"](`${prefix}--label`, {
|
|
163
200
|
[`${prefix}--label--disabled`]: disabled,
|
|
@@ -184,10 +221,10 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
|
|
|
184
221
|
id: helperId,
|
|
185
222
|
className: helperClasses
|
|
186
223
|
}, helperText) : null;
|
|
187
|
-
function onSelectedItemChange(
|
|
224
|
+
function onSelectedItemChange(_ref3) {
|
|
188
225
|
let {
|
|
189
226
|
selectedItem
|
|
190
|
-
} =
|
|
227
|
+
} = _ref3;
|
|
191
228
|
if (onChange) {
|
|
192
229
|
onChange({
|
|
193
230
|
selectedItem: selectedItem ?? null
|
|
@@ -237,6 +274,7 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
|
|
|
237
274
|
}
|
|
238
275
|
};
|
|
239
276
|
const menuProps = getMenuProps();
|
|
277
|
+
const menuRef = mergeRefs["default"](menuProps.ref, refs.setFloating);
|
|
240
278
|
|
|
241
279
|
// Slug is always size `mini`
|
|
242
280
|
let normalizedSlug;
|
|
@@ -261,6 +299,7 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
|
|
|
261
299
|
warnText: warnText,
|
|
262
300
|
light: light,
|
|
263
301
|
isOpen: isOpen,
|
|
302
|
+
ref: refs.setReference,
|
|
264
303
|
id: id
|
|
265
304
|
}, invalid && /*#__PURE__*/React__default["default"].createElement(iconsReact.WarningFilled, {
|
|
266
305
|
className: `${prefix}--list-box__invalid-icon`
|
|
@@ -283,7 +322,9 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
|
|
|
283
322
|
}, selectedItem ? renderSelectedItem ? renderSelectedItem(selectedItem) : itemToString(selectedItem) : label), /*#__PURE__*/React__default["default"].createElement(index["default"].MenuIcon, {
|
|
284
323
|
isOpen: isOpen,
|
|
285
324
|
translateWithId: translateWithId
|
|
286
|
-
})), normalizedSlug, /*#__PURE__*/React__default["default"].createElement(index["default"].Menu,
|
|
325
|
+
})), normalizedSlug, /*#__PURE__*/React__default["default"].createElement(index["default"].Menu, _rollupPluginBabelHelpers["extends"]({}, menuProps, {
|
|
326
|
+
ref: menuRef
|
|
327
|
+
}), isOpen && items.map((item, index$1) => {
|
|
287
328
|
const isObject = item !== null && typeof item === 'object';
|
|
288
329
|
const itemProps = getItemProps({
|
|
289
330
|
item,
|
|
@@ -318,6 +359,10 @@ Dropdown.propTypes = {
|
|
|
318
359
|
* Specify a label to be read by screen readers on the container note.
|
|
319
360
|
*/
|
|
320
361
|
ariaLabel: deprecate["default"](PropTypes__default["default"].string, 'This prop syntax has been deprecated. Please use the new `aria-label`.'),
|
|
362
|
+
/**
|
|
363
|
+
* **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
|
|
364
|
+
*/
|
|
365
|
+
autoAlign: PropTypes__default["default"].bool,
|
|
321
366
|
/**
|
|
322
367
|
* Provide a custom className to be applied on the cds--dropdown node
|
|
323
368
|
*/
|
|
@@ -19,13 +19,14 @@ var Button = require('../Button/Button.js');
|
|
|
19
19
|
require('../Button/Button.Skeleton.js');
|
|
20
20
|
var ButtonSet = require('../ButtonSet/ButtonSet.js');
|
|
21
21
|
var InlineLoading = require('../InlineLoading/InlineLoading.js');
|
|
22
|
+
var index$1 = require('../Layer/index.js');
|
|
22
23
|
var requiredIfGivenPropIsTruthy = require('../../prop-types/requiredIfGivenPropIsTruthy.js');
|
|
23
24
|
var wrapFocus = require('../../internal/wrapFocus.js');
|
|
24
25
|
var debounce = require('lodash.debounce');
|
|
25
26
|
var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
|
|
26
27
|
var setupGetInstanceId = require('../../tools/setupGetInstanceId.js');
|
|
27
28
|
var usePrefix = require('../../internal/usePrefix.js');
|
|
28
|
-
var index$
|
|
29
|
+
var index$2 = require('../IconButton/index.js');
|
|
29
30
|
var noopFn = require('../../internal/noopFn.js');
|
|
30
31
|
require('../Text/index.js');
|
|
31
32
|
var index = require('../FeatureFlags/index.js');
|
|
@@ -246,7 +247,7 @@ const Modal = /*#__PURE__*/React__default["default"].forwardRef(function Modal(_
|
|
|
246
247
|
}
|
|
247
248
|
const modalButton = /*#__PURE__*/React__default["default"].createElement("div", {
|
|
248
249
|
className: `${prefix}--modal-close-button`
|
|
249
|
-
}, /*#__PURE__*/React__default["default"].createElement(index$
|
|
250
|
+
}, /*#__PURE__*/React__default["default"].createElement(index$2.IconButton, {
|
|
250
251
|
className: modalCloseButtonClass,
|
|
251
252
|
label: closeButtonLabel,
|
|
252
253
|
onClick: onRequestClose,
|
|
@@ -277,7 +278,7 @@ const Modal = /*#__PURE__*/React__default["default"].forwardRef(function Modal(_
|
|
|
277
278
|
as: "h3",
|
|
278
279
|
id: modalHeadingId,
|
|
279
280
|
className: `${prefix}--modal-header__heading`
|
|
280
|
-
}, modalHeading), normalizedSlug, !passiveModal && modalButton), /*#__PURE__*/React__default["default"].createElement(
|
|
281
|
+
}, modalHeading), normalizedSlug, !passiveModal && modalButton), /*#__PURE__*/React__default["default"].createElement(index$1.Layer, _rollupPluginBabelHelpers["extends"]({
|
|
281
282
|
ref: contentRef,
|
|
282
283
|
id: modalBodyId,
|
|
283
284
|
className: contentClasses
|
|
@@ -312,7 +313,8 @@ const Modal = /*#__PURE__*/React__default["default"].forwardRef(function Modal(_
|
|
|
312
313
|
className: `${prefix}--inline-loading--btn`,
|
|
313
314
|
onSuccess: onLoadingSuccess
|
|
314
315
|
}))));
|
|
315
|
-
return /*#__PURE__*/React__default["default"].createElement(
|
|
316
|
+
return /*#__PURE__*/React__default["default"].createElement(index$1.Layer, _rollupPluginBabelHelpers["extends"]({}, rest, {
|
|
317
|
+
level: 0,
|
|
316
318
|
onKeyDown: handleKeyDown,
|
|
317
319
|
onMouseDown: handleMousedown,
|
|
318
320
|
onBlur: !focusTrapWithoutSentinels ? handleBlur : () => {},
|