@carbon/react 1.50.0 → 1.51.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 +844 -926
- package/README.md +19 -0
- package/es/components/AiSkeleton/AiSkeletonIcon.d.ts +32 -0
- package/es/components/AiSkeleton/AiSkeletonPlaceholder.d.ts +24 -0
- package/es/components/AiSkeleton/AiSkeletonText.d.ts +55 -0
- package/es/components/AiSkeleton/index.d.ts +10 -0
- package/es/components/ComposedModal/ComposedModal.js +32 -8
- package/es/components/Copy/Copy.js +1 -1
- package/es/components/DataTable/DataTable.d.ts +2 -2
- package/es/components/DataTable/TableToolbarSearch.d.ts +11 -38
- package/es/components/DataTable/TableToolbarSearch.js +1 -1
- package/es/components/Modal/Modal.js +25 -6
- package/es/components/MultiSelect/MultiSelect.d.ts +4 -0
- package/es/components/MultiSelect/MultiSelect.js +10 -1
- package/es/components/NumberInput/NumberInput.js +1 -1
- package/es/components/PaginationNav/PaginationNav.d.ts +45 -0
- package/es/components/PaginationNav/PaginationNav.js +24 -25
- package/es/components/PaginationNav/index.d.ts +9 -0
- package/es/components/Tabs/Tabs.js +2 -1
- package/es/components/Tile/Tile.d.ts +2 -2
- package/es/components/Tile/Tile.js +2 -2
- package/es/index.js +1 -1
- package/lib/components/AiSkeleton/AiSkeletonIcon.d.ts +32 -0
- package/lib/components/AiSkeleton/AiSkeletonPlaceholder.d.ts +24 -0
- package/lib/components/AiSkeleton/AiSkeletonText.d.ts +55 -0
- package/lib/components/AiSkeleton/index.d.ts +10 -0
- package/lib/components/ComposedModal/ComposedModal.js +32 -7
- package/lib/components/Copy/Copy.js +1 -1
- package/lib/components/DataTable/DataTable.d.ts +2 -2
- package/lib/components/DataTable/TableToolbarSearch.d.ts +11 -38
- package/lib/components/DataTable/TableToolbarSearch.js +1 -1
- package/lib/components/Modal/Modal.js +25 -5
- package/lib/components/MultiSelect/MultiSelect.d.ts +4 -0
- package/lib/components/MultiSelect/MultiSelect.js +10 -1
- package/lib/components/NumberInput/NumberInput.js +1 -1
- package/lib/components/PaginationNav/PaginationNav.d.ts +45 -0
- package/lib/components/PaginationNav/PaginationNav.js +24 -25
- package/lib/components/PaginationNav/index.d.ts +9 -0
- package/lib/components/Tabs/Tabs.js +2 -1
- package/lib/components/Tile/Tile.d.ts +2 -2
- package/lib/components/Tile/Tile.js +2 -2
- package/lib/index.js +2 -2
- package/package.json +4 -4
- package/scss/components/skeleton-styles/_ai-skeleton-styles.scss +9 -0
package/README.md
CHANGED
|
@@ -51,6 +51,25 @@ to include `node_modules` in its `includePaths` option. For more information,
|
|
|
51
51
|
checkout the [configuration](../styles/docs/sass.md#configuration) section in
|
|
52
52
|
our Sass docs.
|
|
53
53
|
|
|
54
|
+
### TypeScript
|
|
55
|
+
|
|
56
|
+
There is an ongoing project to add `*.d.ts` files to `@carbon/react`. Though not
|
|
57
|
+
all components have yet been typed, you can still use the project successfully
|
|
58
|
+
in a TypeScript setting, provided you amend to your `tsconfig.json` or
|
|
59
|
+
equivalent configuration file. Include the `skipLibCheck: true` compiler option:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"compilerOptions": {
|
|
64
|
+
"skipLibCheck": true
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
To track the progress of TypeScript adoption, check out:
|
|
70
|
+
|
|
71
|
+
- [TypeScript Adoption](https://github.com/orgs/carbon-design-system/projects/53)
|
|
72
|
+
|
|
54
73
|
## Usage
|
|
55
74
|
|
|
56
75
|
The `@carbon/react` package provides components and icons for the Carbon Design
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2024
|
|
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 React from 'react';
|
|
9
|
+
interface AiSkeletonIconProps {
|
|
10
|
+
/**
|
|
11
|
+
* Specify an optional className to add.
|
|
12
|
+
*/
|
|
13
|
+
className?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The CSS styles.
|
|
16
|
+
*/
|
|
17
|
+
style?: React.CSSProperties;
|
|
18
|
+
}
|
|
19
|
+
declare const AiSkeletonIcon: {
|
|
20
|
+
({ className, ...rest }: AiSkeletonIconProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
propTypes: {
|
|
22
|
+
/**
|
|
23
|
+
* Specify an optional className to add.
|
|
24
|
+
*/
|
|
25
|
+
className: PropTypes.Requireable<string>;
|
|
26
|
+
/**
|
|
27
|
+
* The CSS styles.
|
|
28
|
+
*/
|
|
29
|
+
style: PropTypes.Requireable<object>;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export default AiSkeletonIcon;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2024
|
|
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
|
+
export interface AiSkeletonPlaceholderProps {
|
|
9
|
+
/**
|
|
10
|
+
* Add a custom class to the component to set the height and width
|
|
11
|
+
*/
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
declare const AiSkeletonPlaceholder: {
|
|
15
|
+
({ className, ...other }: AiSkeletonPlaceholderProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
propTypes: {
|
|
17
|
+
/**
|
|
18
|
+
* Add a custom class to the component
|
|
19
|
+
* to set the height and width
|
|
20
|
+
*/
|
|
21
|
+
className: PropTypes.Requireable<string>;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export default AiSkeletonPlaceholder;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2024
|
|
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
|
+
interface AiSkeletonTextProps {
|
|
9
|
+
/**
|
|
10
|
+
* Specify an optional className to be applied to the container node.
|
|
11
|
+
*/
|
|
12
|
+
className?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Generates skeleton text at a larger size.
|
|
15
|
+
*/
|
|
16
|
+
heading?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The number of lines shown if paragraph is true.
|
|
19
|
+
*/
|
|
20
|
+
lineCount?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Set this to true to generate multiple lines of text.
|
|
23
|
+
*/
|
|
24
|
+
paragraph?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Width (in px or %) of single line of text or max-width of paragraph lines.
|
|
27
|
+
*/
|
|
28
|
+
width?: string;
|
|
29
|
+
}
|
|
30
|
+
declare const AiSkeletonText: {
|
|
31
|
+
({ className, ...rest }: AiSkeletonTextProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
propTypes: {
|
|
33
|
+
/**
|
|
34
|
+
* Specify an optional className to be applied to the container node
|
|
35
|
+
*/
|
|
36
|
+
className: PropTypes.Requireable<string>;
|
|
37
|
+
/**
|
|
38
|
+
* generates skeleton text at a larger size
|
|
39
|
+
*/
|
|
40
|
+
heading: PropTypes.Requireable<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* the number of lines shown if paragraph is true
|
|
43
|
+
*/
|
|
44
|
+
lineCount: PropTypes.Requireable<number>;
|
|
45
|
+
/**
|
|
46
|
+
* will generate multiple lines of text
|
|
47
|
+
*/
|
|
48
|
+
paragraph: PropTypes.Requireable<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* width (in px or %) of single line of text or max-width of paragraph lines
|
|
51
|
+
*/
|
|
52
|
+
width: PropTypes.Requireable<string>;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
export default AiSkeletonText;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2024
|
|
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 AiSkeletonPlaceholder from './AiSkeletonPlaceholder';
|
|
8
|
+
import AiSkeletonIcon from './AiSkeletonIcon';
|
|
9
|
+
import AiSkeletonText from './AiSkeletonText';
|
|
10
|
+
export { AiSkeletonText, AiSkeletonIcon, AiSkeletonPlaceholder };
|
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
-
import React__default, {
|
|
9
|
+
import React__default, { useRef, useState, useEffect } from 'react';
|
|
10
10
|
import { isElement } from 'react-is';
|
|
11
11
|
import PropTypes from 'prop-types';
|
|
12
12
|
import { ModalHeader } from './ModalHeader.js';
|
|
13
13
|
import { ModalFooter } from './ModalFooter.js';
|
|
14
|
+
import debounce from 'lodash.debounce';
|
|
15
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
16
|
+
import mergeRefs from '../../tools/mergeRefs.js';
|
|
14
17
|
import cx from 'classnames';
|
|
15
18
|
import toggleClass from '../../tools/toggleClass.js';
|
|
16
19
|
import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy.js';
|
|
@@ -28,18 +31,39 @@ const ModalBody = /*#__PURE__*/React__default.forwardRef(function ModalBody(_ref
|
|
|
28
31
|
...rest
|
|
29
32
|
} = _ref;
|
|
30
33
|
const prefix = usePrefix();
|
|
31
|
-
const
|
|
32
|
-
const
|
|
34
|
+
const contentRef = useRef(null);
|
|
35
|
+
const [isScrollable, setIsScrollable] = useState(false);
|
|
36
|
+
const contentClass = cx({
|
|
37
|
+
[`${prefix}--modal-content`]: true,
|
|
38
|
+
[`${prefix}--modal-content--with-form`]: hasForm,
|
|
39
|
+
[`${prefix}--modal-scroll-content`]: hasScrollingContent || isScrollable,
|
|
40
|
+
customClassName
|
|
41
|
+
});
|
|
42
|
+
useIsomorphicEffect(() => {
|
|
43
|
+
if (contentRef.current) {
|
|
44
|
+
setIsScrollable(contentRef.current.scrollHeight > contentRef.current.clientHeight);
|
|
45
|
+
}
|
|
46
|
+
function handler() {
|
|
47
|
+
if (contentRef.current) {
|
|
48
|
+
setIsScrollable(contentRef.current.scrollHeight > contentRef.current.clientHeight);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const debouncedHandler = debounce(handler, 200);
|
|
52
|
+
window.addEventListener('resize', debouncedHandler);
|
|
53
|
+
return () => {
|
|
54
|
+
debouncedHandler.cancel();
|
|
55
|
+
window.removeEventListener('resize', debouncedHandler);
|
|
56
|
+
};
|
|
57
|
+
}, []);
|
|
58
|
+
const hasScrollingContentProps = hasScrollingContent || isScrollable ? {
|
|
33
59
|
tabIndex: 0,
|
|
34
60
|
role: 'region'
|
|
35
61
|
} : {};
|
|
36
|
-
return /*#__PURE__*/React__default.createElement(
|
|
62
|
+
return /*#__PURE__*/React__default.createElement("div", _extends({
|
|
37
63
|
className: contentClass
|
|
38
64
|
}, hasScrollingContentProps, rest, {
|
|
39
|
-
ref: ref
|
|
40
|
-
}), children)
|
|
41
|
-
className: `${prefix}--modal-content--overflow-indicator`
|
|
42
|
-
}));
|
|
65
|
+
ref: mergeRefs(contentRef, ref)
|
|
66
|
+
}), children);
|
|
43
67
|
});
|
|
44
68
|
ModalBody.propTypes = {
|
|
45
69
|
/**
|
|
@@ -53,7 +53,7 @@ export interface DataTableRow<ColTypes extends any[]> {
|
|
|
53
53
|
export interface DataTableHeader {
|
|
54
54
|
key: string;
|
|
55
55
|
header: React.ReactNode;
|
|
56
|
-
slug
|
|
56
|
+
slug?: React.ReactElement;
|
|
57
57
|
}
|
|
58
58
|
export interface DataTableRenderProps<RowType, ColTypes extends any[]> {
|
|
59
59
|
headers: Array<DataTableHeader>;
|
|
@@ -341,7 +341,7 @@ declare class DataTable<RowType, ColTypes extends any[]> extends React.Component
|
|
|
341
341
|
sortDirection: DataTableSortState;
|
|
342
342
|
isSortable: boolean | undefined;
|
|
343
343
|
isSortHeader: boolean;
|
|
344
|
-
slug: React.ReactElement<any, string | React.JSXElementConstructor<any
|
|
344
|
+
slug: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
|
|
345
345
|
onClick: (event: any) => void;
|
|
346
346
|
};
|
|
347
347
|
/**
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import { ChangeEvent, FocusEvent, ReactNode } from 'react';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
import { SearchProps } from '../Search';
|
|
10
|
+
import { InternationalProps } from '../../types/common';
|
|
11
|
+
export type TableToolbarTranslationKey = 'carbon.table.toolbar.search.label' | 'carbon.table.toolbar.search.placeholder';
|
|
12
|
+
type ExcludedInheritedProps = 'defaultValue' | 'labelText' | 'onBlur' | 'onChange' | 'onExpand' | 'onFocus' | 'tabIndex';
|
|
13
|
+
export type TableToolbarSearchHandleExpand = (event: FocusEvent<HTMLInputElement>, newValue?: boolean) => void;
|
|
14
|
+
export interface TableToolbarSearchProps extends Omit<SearchProps, ExcludedInheritedProps>, InternationalProps<TableToolbarTranslationKey> {
|
|
15
15
|
/**
|
|
16
16
|
* Specifies if the search should initially render in an expanded state
|
|
17
17
|
*/
|
|
@@ -20,70 +20,43 @@ export interface TableToolbarSearchProps {
|
|
|
20
20
|
* Provide an optional default value for the Search component
|
|
21
21
|
*/
|
|
22
22
|
defaultValue?: string;
|
|
23
|
-
/**
|
|
24
|
-
* Specifies if the search should be disabled
|
|
25
|
-
*/
|
|
26
|
-
disabled?: boolean;
|
|
27
23
|
/**
|
|
28
24
|
* Specifies if the search should expand
|
|
29
25
|
*/
|
|
30
26
|
expanded?: boolean;
|
|
31
|
-
/**
|
|
32
|
-
* Provide an optional id for the search container
|
|
33
|
-
*/
|
|
34
|
-
id?: string;
|
|
35
27
|
/**
|
|
36
28
|
* Provide an optional label text for the Search component icon
|
|
37
29
|
*/
|
|
38
|
-
labelText?:
|
|
30
|
+
labelText?: ReactNode;
|
|
39
31
|
/**
|
|
40
32
|
* Provide an optional function to be called when the search input loses focus, this will be
|
|
41
33
|
* passed the event as the first parameter and a function to handle the expanding of the search
|
|
42
34
|
* input as the second
|
|
43
35
|
*/
|
|
44
|
-
onBlur
|
|
36
|
+
onBlur?(event: FocusEvent<HTMLInputElement>, handleExpand: TableToolbarSearchHandleExpand): void;
|
|
45
37
|
/**
|
|
46
38
|
* Provide an optional hook that is called each time the input is updated
|
|
47
39
|
*/
|
|
48
40
|
onChange?: (event: '' | ChangeEvent<HTMLInputElement>, value?: string) => void;
|
|
49
|
-
/**
|
|
50
|
-
* Optional callback called when the search value is cleared.
|
|
51
|
-
*/
|
|
52
|
-
onClear?: () => void;
|
|
53
41
|
/**
|
|
54
42
|
* Provide an optional hook that is called each time the input is expanded
|
|
55
43
|
*/
|
|
56
|
-
onExpand
|
|
44
|
+
onExpand?(event: FocusEvent<HTMLInputElement>, newExpand: boolean): void;
|
|
57
45
|
/**
|
|
58
46
|
* Provide an optional function to be called when the search input gains focus, this will be
|
|
59
47
|
* passed the event as the first parameter and a function to handle the expanding of the search
|
|
60
48
|
* input as the second.
|
|
61
49
|
*/
|
|
62
|
-
onFocus
|
|
50
|
+
onFocus?(event: FocusEvent<HTMLInputElement>, handleExpand: TableToolbarSearchHandleExpand): void;
|
|
63
51
|
/**
|
|
64
|
-
* Whether the search should be allowed to expand
|
|
52
|
+
* Whether the search should be allowed to expand.
|
|
65
53
|
*/
|
|
66
54
|
persistent?: boolean;
|
|
67
|
-
/**
|
|
68
|
-
* Provide an optional placeholder text for the Search component
|
|
69
|
-
*/
|
|
70
|
-
placeholder?: string;
|
|
71
55
|
/**
|
|
72
56
|
* Provide an optional className for the overall container of the Search
|
|
73
57
|
*/
|
|
74
58
|
searchContainerClass?: string;
|
|
75
|
-
/**
|
|
76
|
-
* Specify the size of the Search
|
|
77
|
-
*/
|
|
78
|
-
size?: 'sm' | 'md' | 'lg';
|
|
79
|
-
/**
|
|
80
|
-
* Optional prop to specify the tabIndex of the <Search> (in expanded state) or the container (in collapsed state)
|
|
81
|
-
*/
|
|
82
59
|
tabIndex?: number | string;
|
|
83
|
-
/**
|
|
84
|
-
* Provide custom text for the component for each translation id
|
|
85
|
-
*/
|
|
86
|
-
translateWithId?: (id: string) => string;
|
|
87
60
|
}
|
|
88
61
|
declare const TableToolbarSearch: {
|
|
89
62
|
({ className, searchContainerClass, onChange: onChangeProp, onClear, translateWithId: t, placeholder, labelText, expanded: expandedProp, defaultExpanded, defaultValue, disabled, onExpand, persistent, id, onBlur, onFocus, size, tabIndex, ...rest }: TableToolbarSearchProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -48,7 +48,7 @@ const TableToolbarSearch = _ref => {
|
|
|
48
48
|
const {
|
|
49
49
|
current: controlled
|
|
50
50
|
} = useRef(expandedProp !== undefined);
|
|
51
|
-
const [expandedState, setExpandedState] = useState(defaultExpanded || defaultValue);
|
|
51
|
+
const [expandedState, setExpandedState] = useState(Boolean(defaultExpanded || defaultValue));
|
|
52
52
|
const expanded = controlled ? expandedProp : expandedState;
|
|
53
53
|
const [value, setValue] = useState(defaultValue || '');
|
|
54
54
|
const uniqueId = useMemo(getInstanceId, []);
|
|
@@ -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__default, { useRef, useEffect } from 'react';
|
|
10
|
+
import React__default, { useRef, useState, useEffect } from 'react';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { Close } from '@carbon/icons-react';
|
|
13
13
|
import toggleClass from '../../tools/toggleClass.js';
|
|
@@ -17,6 +17,8 @@ import ButtonSet from '../ButtonSet/ButtonSet.js';
|
|
|
17
17
|
import InlineLoading from '../InlineLoading/InlineLoading.js';
|
|
18
18
|
import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy.js';
|
|
19
19
|
import wrapFocus, { elementOrParentIsFloatingMenu } from '../../internal/wrapFocus.js';
|
|
20
|
+
import debounce from 'lodash.debounce';
|
|
21
|
+
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
20
22
|
import setupGetInstanceId from '../../tools/setupGetInstanceId.js';
|
|
21
23
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
22
24
|
import { IconButton } from '../IconButton/index.js';
|
|
@@ -66,9 +68,11 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
66
68
|
const prefix = usePrefix();
|
|
67
69
|
const button = useRef(null);
|
|
68
70
|
const secondaryButton = useRef();
|
|
71
|
+
const contentRef = useRef(null);
|
|
69
72
|
const innerModal = useRef(null);
|
|
70
73
|
const startTrap = useRef(null);
|
|
71
74
|
const endTrap = useRef(null);
|
|
75
|
+
const [isScrollable, setIsScrollable] = useState(false);
|
|
72
76
|
const modalInstanceId = `modal-${getInstanceId()}`;
|
|
73
77
|
const modalLabelId = `${prefix}--modal-header__label--${modalInstanceId}`;
|
|
74
78
|
const modalHeadingId = `${prefix}--modal-header__heading--${modalInstanceId}`;
|
|
@@ -134,7 +138,7 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
134
138
|
[`${prefix}--modal-container--full-width`]: isFullWidth
|
|
135
139
|
});
|
|
136
140
|
const contentClasses = cx(`${prefix}--modal-content`, {
|
|
137
|
-
[`${prefix}--modal-scroll-content`]: hasScrollingContent
|
|
141
|
+
[`${prefix}--modal-scroll-content`]: hasScrollingContent || isScrollable
|
|
138
142
|
});
|
|
139
143
|
const footerClasses = cx(`${prefix}--modal-footer`, {
|
|
140
144
|
[`${prefix}--modal-footer--three-button`]: Array.isArray(secondaryButtons) && secondaryButtons.length === 2
|
|
@@ -146,7 +150,7 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
146
150
|
const modalHeadingStr = asStringOrUndefined(modalHeading);
|
|
147
151
|
const ariaLabel = modalLabelStr || ariaLabelProp || modalAriaLabel || modalHeadingStr;
|
|
148
152
|
const getAriaLabelledBy = modalLabel ? modalLabelId : modalHeadingId;
|
|
149
|
-
const hasScrollingContentProps = hasScrollingContent ? {
|
|
153
|
+
const hasScrollingContentProps = hasScrollingContent || isScrollable ? {
|
|
150
154
|
tabIndex: 0,
|
|
151
155
|
role: 'region',
|
|
152
156
|
'aria-label': ariaLabel,
|
|
@@ -194,6 +198,22 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
194
198
|
focusButton(innerModal.current);
|
|
195
199
|
}
|
|
196
200
|
}, [open, selectorPrimaryFocus, danger, prefix]);
|
|
201
|
+
useIsomorphicEffect(() => {
|
|
202
|
+
if (contentRef.current) {
|
|
203
|
+
setIsScrollable(contentRef.current.scrollHeight > contentRef.current.clientHeight);
|
|
204
|
+
}
|
|
205
|
+
function handler() {
|
|
206
|
+
if (contentRef.current) {
|
|
207
|
+
setIsScrollable(contentRef.current.scrollHeight > contentRef.current.clientHeight);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const debouncedHandler = debounce(handler, 200);
|
|
211
|
+
window.addEventListener('resize', debouncedHandler);
|
|
212
|
+
return () => {
|
|
213
|
+
debouncedHandler.cancel();
|
|
214
|
+
window.removeEventListener('resize', debouncedHandler);
|
|
215
|
+
};
|
|
216
|
+
}, []);
|
|
197
217
|
|
|
198
218
|
// Slug is always size `lg`
|
|
199
219
|
let normalizedSlug;
|
|
@@ -237,11 +257,10 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
237
257
|
id: modalHeadingId,
|
|
238
258
|
className: `${prefix}--modal-header__heading`
|
|
239
259
|
}, modalHeading), normalizedSlug, !passiveModal && modalButton), /*#__PURE__*/React__default.createElement("div", _extends({
|
|
260
|
+
ref: contentRef,
|
|
240
261
|
id: modalBodyId,
|
|
241
262
|
className: contentClasses
|
|
242
|
-
}, hasScrollingContentProps), children),
|
|
243
|
-
className: `${prefix}--modal-content--overflow-indicator`
|
|
244
|
-
}), !passiveModal && /*#__PURE__*/React__default.createElement(ButtonSet, {
|
|
263
|
+
}, hasScrollingContentProps), children), !passiveModal && /*#__PURE__*/React__default.createElement(ButtonSet, {
|
|
245
264
|
className: footerClasses,
|
|
246
265
|
"aria-busy": loadingActive
|
|
247
266
|
}, Array.isArray(secondaryButtons) && secondaryButtons.length <= 2 ? secondaryButtons.map((_ref3, i) => {
|
|
@@ -51,6 +51,10 @@ interface MultiSelectSortingProps<ItemType> {
|
|
|
51
51
|
}
|
|
52
52
|
export interface MultiSelectProps<ItemType> extends MultiSelectSortingProps<ItemType>, InternationalProps<'close.menu' | 'open.menu' | 'clear.all' | 'clear.selection'> {
|
|
53
53
|
className?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Specify the text that should be read for screen readers that describes that all items are deleted
|
|
56
|
+
*/
|
|
57
|
+
clearAnnouncement?: string;
|
|
54
58
|
/**
|
|
55
59
|
* Specify the text that should be read for screen readers that describes total items selected
|
|
56
60
|
*/
|
|
@@ -71,6 +71,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
71
71
|
sortItems = defaultSortItems,
|
|
72
72
|
compareItems = defaultCompareItems,
|
|
73
73
|
clearSelectionText = 'To clear selection, press Delete or Backspace',
|
|
74
|
+
clearAnnouncement = 'all items have been cleared',
|
|
74
75
|
clearSelectionDescription = 'Total items selected: ',
|
|
75
76
|
light,
|
|
76
77
|
invalid,
|
|
@@ -102,6 +103,7 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
102
103
|
const [isOpen, setIsOpen] = useState(open || false);
|
|
103
104
|
const [prevOpenProp, setPrevOpenProp] = useState(open);
|
|
104
105
|
const [topItems, setTopItems] = useState([]);
|
|
106
|
+
const [itemsCleared, setItemsCleared] = useState(false);
|
|
105
107
|
const {
|
|
106
108
|
selectedItems: controlledSelectedItems,
|
|
107
109
|
onItemChange,
|
|
@@ -148,7 +150,11 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
148
150
|
clearSelection();
|
|
149
151
|
e.stopPropagation();
|
|
150
152
|
}
|
|
153
|
+
if (!isOpen && match(e, Delete) && selectedItems.length > 0) {
|
|
154
|
+
setItemsCleared(true);
|
|
155
|
+
}
|
|
151
156
|
if ((match(e, Space) || match(e, ArrowDown) || match(e, Enter)) && !isOpen) {
|
|
157
|
+
setItemsCleared(false);
|
|
152
158
|
setIsOpenWrapper(true);
|
|
153
159
|
}
|
|
154
160
|
}
|
|
@@ -383,7 +389,10 @@ const MultiSelect = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
383
389
|
}, itemToElement ? /*#__PURE__*/React__default.createElement(ItemToElement, _extends({
|
|
384
390
|
key: itemProps.id
|
|
385
391
|
}, item)) : itemText)));
|
|
386
|
-
}))
|
|
392
|
+
})), itemsCleared && /*#__PURE__*/React__default.createElement("span", {
|
|
393
|
+
"aria-live": "assertive",
|
|
394
|
+
"aria-label": clearAnnouncement
|
|
395
|
+
})), !inline && !invalid && !warn && helperText && /*#__PURE__*/React__default.createElement("div", {
|
|
387
396
|
id: helperId,
|
|
388
397
|
className: helperClasses
|
|
389
398
|
}, helperText));
|
|
@@ -130,7 +130,7 @@ const NumberInput = /*#__PURE__*/React__default.forwardRef(function NumberInput(
|
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
132
|
const state = {
|
|
133
|
-
value: event.target.value,
|
|
133
|
+
value: Number(event.target.value),
|
|
134
134
|
direction: value < event.target.value ? 'up' : 'down'
|
|
135
135
|
};
|
|
136
136
|
setValue(state.value);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2020
|
|
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 from 'react';
|
|
8
|
+
interface PaginationNavProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
9
|
+
/**
|
|
10
|
+
* Additional CSS class names.
|
|
11
|
+
*/
|
|
12
|
+
className?: string;
|
|
13
|
+
/**
|
|
14
|
+
* If true, the '...' pagination overflow will not render page links between the first and last rendered buttons.
|
|
15
|
+
* Set this to true if you are having performance problems with large data sets.
|
|
16
|
+
*/
|
|
17
|
+
disableOverflow?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The number of items to be shown.
|
|
20
|
+
*/
|
|
21
|
+
itemsShown?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Whether user should be able to loop through the items when reaching first / last.
|
|
24
|
+
*/
|
|
25
|
+
loop?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The callback function called when the current page changes.
|
|
28
|
+
*/
|
|
29
|
+
onChange?: (data: number) => void;
|
|
30
|
+
/**
|
|
31
|
+
* The index of current page.
|
|
32
|
+
*/
|
|
33
|
+
page?: number;
|
|
34
|
+
/**
|
|
35
|
+
* The total number of items.
|
|
36
|
+
*/
|
|
37
|
+
totalItems?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Specify a custom translation function that takes in a message identifier
|
|
40
|
+
* and returns the localized string for the message
|
|
41
|
+
*/
|
|
42
|
+
translateWithId?: (id: string) => string;
|
|
43
|
+
}
|
|
44
|
+
declare const PaginationNav: React.ForwardRefExoticComponent<PaginationNavProps & React.RefAttributes<HTMLElement>>;
|
|
45
|
+
export default PaginationNav;
|