@carbon/react 1.31.3 → 1.32.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/README.md +1 -1
- package/es/components/Accordion/Accordion.Skeleton.d.ts +64 -0
- package/es/components/Accordion/Accordion.Skeleton.js +3 -3
- package/es/components/Accordion/Accordion.d.ts +65 -0
- package/es/components/Accordion/Accordion.js +5 -6
- package/es/components/Accordion/AccordionItem.d.ts +105 -0
- package/es/components/Accordion/AccordionItem.js +12 -9
- package/es/components/Accordion/AccordionProvider.d.ts +20 -0
- package/es/components/Accordion/AccordionProvider.js +25 -0
- package/es/components/Accordion/index.d.ts +11 -0
- package/es/components/Button/Button.Skeleton.d.ts +28 -0
- package/es/components/Button/Button.Skeleton.js +5 -3
- package/es/components/Button/Button.d.ts +72 -0
- package/es/components/Button/Button.js +13 -10
- package/es/components/Button/index.d.ts +11 -0
- package/es/components/Button/index.js +2 -1
- package/es/components/ButtonSet/ButtonSet.d.ts +17 -0
- package/es/components/ButtonSet/ButtonSet.js +1 -2
- package/es/components/ButtonSet/index.d.ts +9 -0
- package/es/components/CodeSnippet/CodeSnippet.js +1 -0
- package/es/components/ComboButton/index.js +1 -0
- package/es/components/ComposedModal/ComposedModal.d.ts +70 -0
- package/es/components/ComposedModal/ComposedModal.js +58 -67
- package/es/components/ComposedModal/ModalFooter.d.ts +71 -0
- package/es/components/ComposedModal/ModalFooter.js +22 -19
- package/es/components/ComposedModal/ModalHeader.d.ts +58 -0
- package/es/components/ComposedModal/ModalHeader.js +8 -25
- package/es/components/ComposedModal/index.d.ts +9 -0
- package/es/components/ContainedList/ContainedList.js +12 -1
- package/es/components/ContentSwitcher/ContentSwitcher.d.ts +109 -0
- package/es/components/ContentSwitcher/ContentSwitcher.js +14 -6
- package/es/components/DangerButton/DangerButton.d.ts +9 -0
- package/es/components/DangerButton/DangerButton.js +2 -2
- package/es/components/DangerButton/index.d.ts +9 -0
- package/es/components/DataTable/TableBatchAction.js +1 -0
- package/es/components/DataTable/TableBatchActions.js +1 -0
- package/es/components/DataTable/TableBody.d.ts +29 -0
- package/es/components/DataTable/TableBody.js +2 -3
- package/es/components/DataTable/TableContainer.d.ts +51 -0
- package/es/components/DataTable/TableContainer.js +3 -4
- package/es/components/DataTable/TableExpandHeader.d.ts +86 -0
- package/es/components/DataTable/TableExpandHeader.js +4 -5
- package/es/components/DatePicker/plugins/fixEventsPlugin.js +12 -16
- package/es/components/Dropdown/Dropdown.js +1 -0
- package/es/components/FluidTextInput/FluidTextInput.js +1 -0
- package/es/components/FormGroup/FormGroup.d.ts +80 -0
- package/es/components/IconButton/index.js +3 -2
- package/es/components/Layout/index.d.ts +74 -0
- package/es/components/Layout/index.js +14 -5
- package/es/components/Link/Link.d.ts +2 -2
- package/es/components/Link/Link.js +2 -1
- package/es/components/MenuButton/index.js +1 -0
- package/es/components/Modal/Modal.js +1 -0
- package/es/components/ModalWrapper/ModalWrapper.js +1 -0
- package/es/components/Notification/Notification.d.ts +531 -0
- package/es/components/Notification/Notification.js +40 -6
- package/es/components/Notification/index.d.ts +7 -0
- package/es/components/PrimaryButton/PrimaryButton.js +1 -0
- package/es/components/SecondaryButton/SecondaryButton.js +1 -0
- package/es/components/Select/Select.d.ts +1 -1
- package/es/components/SkeletonText/SkeletonText.d.ts +61 -0
- package/es/components/SkeletonText/SkeletonText.js +15 -17
- package/es/components/SkeletonText/index.d.ts +9 -0
- package/es/components/Switch/Switch.d.ts +56 -0
- package/es/components/Switch/Switch.js +4 -4
- package/es/components/Tab/index.d.ts +9 -0
- package/es/components/TabContent/TabContent.d.ts +40 -0
- package/es/components/TabContent/TabContent.js +6 -12
- package/es/components/TabContent/index.d.ts +10 -0
- package/es/components/Tabs/Tabs.Skeleton.d.ts +33 -0
- package/es/components/Tabs/Tabs.Skeleton.js +2 -2
- package/es/components/Tabs/Tabs.d.ts +311 -0
- package/es/components/Tabs/Tabs.js +151 -97
- package/es/components/Tabs/index.d.ts +10 -0
- package/es/components/Tabs/usePressable.js +11 -0
- package/es/components/TextInput/ControlledPasswordInput.d.ts +90 -0
- package/es/components/TextInput/ControlledPasswordInput.js +5 -6
- package/es/components/Tile/Tile.d.ts +153 -0
- package/es/components/Tile/Tile.js +62 -74
- package/es/components/Tile/index.d.ts +7 -0
- package/es/components/Toggle/Toggle.Skeleton.d.ts +3 -47
- package/es/components/Toggle/Toggle.Skeleton.js +24 -64
- package/es/components/Toggle/Toggle.js +1 -1
- package/es/components/UIShell/HeaderGlobalAction.js +1 -0
- package/es/components/UIShell/HeaderPanel.js +61 -5
- package/es/components/UIShell/SideNav.d.ts +1 -1
- package/es/components/UIShell/Switcher.js +45 -5
- package/es/components/UIShell/SwitcherItem.js +45 -6
- package/es/index.js +16 -16
- package/es/internal/keyboard/match.js +2 -2
- package/es/internal/useControllableState.js +2 -2
- package/es/internal/useMatchMedia.js +44 -0
- package/es/internal/wrapFocus.js +6 -6
- package/es/prop-types/requiredIfGivenPropIsTruthy.js +1 -1
- package/es/prop-types/types.js +3 -0
- package/lib/components/Accordion/Accordion.Skeleton.d.ts +64 -0
- package/lib/components/Accordion/Accordion.Skeleton.js +3 -3
- package/lib/components/Accordion/Accordion.d.ts +65 -0
- package/lib/components/Accordion/Accordion.js +5 -6
- package/lib/components/Accordion/AccordionItem.d.ts +105 -0
- package/lib/components/Accordion/AccordionItem.js +11 -8
- package/lib/components/Accordion/AccordionProvider.d.ts +20 -0
- package/lib/components/Accordion/AccordionProvider.js +34 -0
- package/lib/components/Accordion/index.d.ts +11 -0
- package/lib/components/Button/Button.Skeleton.d.ts +28 -0
- package/lib/components/Button/Button.Skeleton.js +5 -3
- package/lib/components/Button/Button.d.ts +72 -0
- package/lib/components/Button/Button.js +18 -11
- package/lib/components/Button/index.d.ts +11 -0
- package/lib/components/Button/index.js +6 -0
- package/lib/components/ButtonSet/ButtonSet.d.ts +17 -0
- package/lib/components/ButtonSet/ButtonSet.js +1 -2
- package/lib/components/ButtonSet/index.d.ts +9 -0
- package/lib/components/CodeSnippet/CodeSnippet.js +1 -0
- package/lib/components/ComboButton/index.js +1 -0
- package/lib/components/ComposedModal/ComposedModal.d.ts +70 -0
- package/lib/components/ComposedModal/ComposedModal.js +58 -67
- package/lib/components/ComposedModal/ModalFooter.d.ts +71 -0
- package/lib/components/ComposedModal/ModalFooter.js +22 -19
- package/lib/components/ComposedModal/ModalHeader.d.ts +58 -0
- package/lib/components/ComposedModal/ModalHeader.js +8 -25
- package/lib/components/ComposedModal/index.d.ts +9 -0
- package/lib/components/ContainedList/ContainedList.js +12 -1
- package/lib/components/ContentSwitcher/ContentSwitcher.d.ts +109 -0
- package/lib/components/ContentSwitcher/ContentSwitcher.js +14 -6
- package/lib/components/DangerButton/DangerButton.d.ts +9 -0
- package/lib/components/DangerButton/DangerButton.js +2 -2
- package/lib/components/DangerButton/index.d.ts +9 -0
- package/lib/components/DataTable/TableBatchAction.js +1 -0
- package/lib/components/DataTable/TableBatchActions.js +1 -0
- package/lib/components/DataTable/TableBody.d.ts +29 -0
- package/lib/components/DataTable/TableBody.js +3 -4
- package/lib/components/DataTable/TableContainer.d.ts +51 -0
- package/lib/components/DataTable/TableContainer.js +3 -4
- package/lib/components/DataTable/TableExpandHeader.d.ts +86 -0
- package/lib/components/DataTable/TableExpandHeader.js +4 -5
- package/lib/components/DatePicker/plugins/fixEventsPlugin.js +12 -16
- package/lib/components/Dropdown/Dropdown.js +1 -0
- package/lib/components/FluidTextInput/FluidTextInput.js +1 -0
- package/lib/components/FormGroup/FormGroup.d.ts +80 -0
- package/lib/components/IconButton/index.js +3 -2
- package/lib/components/Layout/index.d.ts +74 -0
- package/lib/components/Layout/index.js +14 -5
- package/lib/components/Link/Link.d.ts +2 -2
- package/lib/components/Link/Link.js +2 -1
- package/lib/components/MenuButton/index.js +1 -0
- package/lib/components/Modal/Modal.js +1 -0
- package/lib/components/ModalWrapper/ModalWrapper.js +1 -0
- package/lib/components/Notification/Notification.d.ts +531 -0
- package/lib/components/Notification/Notification.js +40 -6
- package/lib/components/Notification/index.d.ts +7 -0
- package/lib/components/PrimaryButton/PrimaryButton.js +1 -0
- package/lib/components/SecondaryButton/SecondaryButton.js +1 -0
- package/lib/components/Select/Select.d.ts +1 -1
- package/lib/components/SkeletonText/SkeletonText.d.ts +61 -0
- package/lib/components/SkeletonText/SkeletonText.js +15 -17
- package/lib/components/SkeletonText/index.d.ts +9 -0
- package/lib/components/Switch/Switch.d.ts +56 -0
- package/lib/components/Switch/Switch.js +4 -4
- package/lib/components/Tab/index.d.ts +9 -0
- package/lib/components/TabContent/TabContent.d.ts +40 -0
- package/lib/components/TabContent/TabContent.js +6 -12
- package/lib/components/TabContent/index.d.ts +10 -0
- package/lib/components/Tabs/Tabs.Skeleton.d.ts +33 -0
- package/lib/components/Tabs/Tabs.Skeleton.js +2 -2
- package/lib/components/Tabs/Tabs.d.ts +311 -0
- package/lib/components/Tabs/Tabs.js +150 -96
- package/lib/components/Tabs/index.d.ts +10 -0
- package/lib/components/Tabs/usePressable.js +11 -0
- package/lib/components/TextInput/ControlledPasswordInput.d.ts +90 -0
- package/lib/components/TextInput/ControlledPasswordInput.js +5 -6
- package/lib/components/Tile/Tile.d.ts +153 -0
- package/lib/components/Tile/Tile.js +62 -74
- package/lib/components/Tile/index.d.ts +7 -0
- package/lib/components/Toggle/Toggle.Skeleton.d.ts +3 -47
- package/lib/components/Toggle/Toggle.Skeleton.js +22 -62
- package/lib/components/Toggle/Toggle.js +1 -1
- package/lib/components/UIShell/HeaderGlobalAction.js +1 -0
- package/lib/components/UIShell/HeaderPanel.js +60 -4
- package/lib/components/UIShell/SideNav.d.ts +1 -1
- package/lib/components/UIShell/Switcher.js +44 -4
- package/lib/components/UIShell/SwitcherItem.js +45 -6
- package/lib/index.js +51 -47
- package/lib/internal/keyboard/match.js +2 -2
- package/lib/internal/useControllableState.js +2 -2
- package/lib/internal/useMatchMedia.js +48 -0
- package/lib/internal/wrapFocus.js +6 -6
- package/lib/prop-types/requiredIfGivenPropIsTruthy.js +1 -1
- package/lib/prop-types/types.js +3 -0
- package/package.json +4 -3
|
@@ -13,6 +13,7 @@ import useResizeObserver from 'use-resize-observer/polyfilled';
|
|
|
13
13
|
import { ChevronDown } from '@carbon/icons-react';
|
|
14
14
|
import Copy from '../Copy/Copy.js';
|
|
15
15
|
import Button from '../Button/Button.js';
|
|
16
|
+
import '../Button/Button.Skeleton.js';
|
|
16
17
|
import CopyButton from '../CopyButton/CopyButton.js';
|
|
17
18
|
import uniqueId from '../../tools/uniqueId.js';
|
|
18
19
|
import copy from 'copy-to-clipboard';
|
|
@@ -11,6 +11,7 @@ import PropTypes from 'prop-types';
|
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { ChevronDown } from '@carbon/icons-react';
|
|
13
13
|
import Button from '../Button/Button.js';
|
|
14
|
+
import '../Button/Button.Skeleton.js';
|
|
14
15
|
import { IconButton } from '../IconButton/index.js';
|
|
15
16
|
import { Menu } from '../Menu/Menu.js';
|
|
16
17
|
import { useAttachedMenu } from '../../internal/useAttachedMenu.js';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React, { type MouseEvent, type KeyboardEvent, type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
export interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/** Specify the content to be placed in the ModalBody. */
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
/**
|
|
6
|
+
* Provide whether the modal content has a form element.
|
|
7
|
+
* If `true` is used here, non-form child content should have `bx--modal-content__regular-content` class.
|
|
8
|
+
*/
|
|
9
|
+
hasForm?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Specify whether the modal contains scrolling content
|
|
12
|
+
*/
|
|
13
|
+
hasScrollingContent?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare const ModalBody: React.ForwardRefExoticComponent<ModalBodyProps & React.RefAttributes<HTMLDivElement>>;
|
|
16
|
+
export interface ComposedModalProps extends HTMLAttributes<HTMLDivElement> {
|
|
17
|
+
/**
|
|
18
|
+
* Specify the aria-label for bx--modal-container
|
|
19
|
+
*/
|
|
20
|
+
'aria-label'?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Specify the aria-labelledby for bx--modal-container
|
|
23
|
+
*/
|
|
24
|
+
'aria-labelledby'?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Specify the content to be placed in the ComposedModal
|
|
27
|
+
*/
|
|
28
|
+
children?: ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* Specify an optional className to be applied to the modal root node
|
|
31
|
+
*/
|
|
32
|
+
className?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Specify an optional className to be applied to the modal node
|
|
35
|
+
*/
|
|
36
|
+
containerClassName?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Specify whether the primary button should be replaced with danger button.
|
|
39
|
+
* Note that this prop is not applied if you render primary/danger button by yourself
|
|
40
|
+
*/
|
|
41
|
+
danger?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Specify whether the Modal content should have any inner padding.
|
|
44
|
+
*/
|
|
45
|
+
isFullWidth?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Specify an optional handler for closing modal.
|
|
48
|
+
* Returning `false` here prevents closing modal.
|
|
49
|
+
*/
|
|
50
|
+
onClose?(event: MouseEvent): void | boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Called for all `onKeyDown` events that do not close the modal
|
|
53
|
+
*/
|
|
54
|
+
onKeyDown?(evt: KeyboardEvent): void;
|
|
55
|
+
/**
|
|
56
|
+
* Specify whether the Modal is currently open
|
|
57
|
+
*/
|
|
58
|
+
open?: boolean;
|
|
59
|
+
preventCloseOnClickOutside?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Specify a CSS selector that matches the DOM element that should be
|
|
62
|
+
* focused when the Modal opens
|
|
63
|
+
*/
|
|
64
|
+
selectorPrimaryFocus?: string;
|
|
65
|
+
/** Specify the CSS selectors that match the floating menus. */
|
|
66
|
+
selectorsFloatingMenus?: Array<string | null | undefined>;
|
|
67
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
68
|
+
}
|
|
69
|
+
declare const ComposedModal: React.ForwardRefExoticComponent<ComposedModalProps & React.RefAttributes<HTMLDivElement>>;
|
|
70
|
+
export default ComposedModal;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import React__default, { useState, useRef, useEffect } from 'react';
|
|
10
|
+
import { isElement } from 'react-is';
|
|
10
11
|
import PropTypes from 'prop-types';
|
|
11
12
|
import { ModalHeader } from './ModalHeader.js';
|
|
12
13
|
import { ModalFooter } from './ModalFooter.js';
|
|
@@ -15,6 +16,8 @@ import toggleClass from '../../tools/toggleClass.js';
|
|
|
15
16
|
import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy.js';
|
|
16
17
|
import wrapFocus from '../../internal/wrapFocus.js';
|
|
17
18
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
19
|
+
import { match } from '../../internal/keyboard/match.js';
|
|
20
|
+
import { Escape } from '../../internal/keyboard/keys.js';
|
|
18
21
|
|
|
19
22
|
const ModalBody = /*#__PURE__*/React__default.forwardRef(function ModalBody(_ref, ref) {
|
|
20
23
|
let {
|
|
@@ -25,12 +28,7 @@ const ModalBody = /*#__PURE__*/React__default.forwardRef(function ModalBody(_ref
|
|
|
25
28
|
...rest
|
|
26
29
|
} = _ref;
|
|
27
30
|
const prefix = usePrefix();
|
|
28
|
-
const contentClass = cx({
|
|
29
|
-
[`${prefix}--modal-content`]: true,
|
|
30
|
-
[`${prefix}--modal-content--with-form`]: hasForm,
|
|
31
|
-
[`${prefix}--modal-scroll-content`]: hasScrollingContent,
|
|
32
|
-
[customClassName]: customClassName
|
|
33
|
-
});
|
|
31
|
+
const contentClass = cx(`${prefix}--modal-content`, hasForm && `${prefix}--modal-content--with-form`, hasScrollingContent && `${prefix}--modal-scroll-content`, customClassName);
|
|
34
32
|
const hasScrollingContentProps = hasScrollingContent ? {
|
|
35
33
|
tabIndex: 0,
|
|
36
34
|
role: 'region'
|
|
@@ -47,6 +45,7 @@ ModalBody.propTypes = {
|
|
|
47
45
|
/**
|
|
48
46
|
* Required props for the accessibility label of the header
|
|
49
47
|
*/
|
|
48
|
+
// @ts-expect-error: Built-in prop-types > TS logic doesn't jive well with custom validators
|
|
50
49
|
['aria-label']: requiredIfGivenPropIsTruthy('hasScrollingContent', PropTypes.string),
|
|
51
50
|
/**
|
|
52
51
|
* Specify the content to be placed in the ModalBody
|
|
@@ -85,28 +84,38 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
|
|
|
85
84
|
...rest
|
|
86
85
|
} = _ref2;
|
|
87
86
|
const prefix = usePrefix();
|
|
88
|
-
const [isOpen,
|
|
89
|
-
const [
|
|
90
|
-
const innerModal = useRef();
|
|
91
|
-
const button = useRef();
|
|
92
|
-
const startSentinel = useRef();
|
|
93
|
-
const endSentinel = useRef();
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
const [isOpen, setIsOpen] = useState(!!open);
|
|
88
|
+
const [wasOpen, setWasOpen] = useState(!!open);
|
|
89
|
+
const innerModal = useRef(null);
|
|
90
|
+
const button = useRef(null);
|
|
91
|
+
const startSentinel = useRef(null);
|
|
92
|
+
const endSentinel = useRef(null);
|
|
93
|
+
|
|
94
|
+
// Kepp track of modal open/close state
|
|
95
|
+
// and propagate it to the document.body
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (open !== wasOpen) {
|
|
98
|
+
setIsOpen(!!open);
|
|
99
|
+
setWasOpen(!!open);
|
|
100
|
+
toggleClass(document.body, `${prefix}--body--with-modal-open`, !!open);
|
|
101
|
+
}
|
|
102
|
+
}, [open, wasOpen, prefix]);
|
|
103
|
+
// Remove the document.body className on unmount
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
return () => {
|
|
106
|
+
toggleClass(document.body, `${prefix}--body--with-modal-open`, false);
|
|
107
|
+
};
|
|
108
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
109
|
+
|
|
98
110
|
function handleKeyDown(evt) {
|
|
99
|
-
|
|
100
|
-
if (evt.which === 27) {
|
|
111
|
+
if (match(evt, Escape)) {
|
|
101
112
|
closeModal(evt);
|
|
102
113
|
}
|
|
103
|
-
onKeyDown(evt);
|
|
114
|
+
onKeyDown?.(evt);
|
|
104
115
|
}
|
|
105
116
|
function handleMousedown(evt) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
if (innerModal.current && !innerModal.current.contains(evt.target)) {
|
|
117
|
+
const isInside = innerModal.current?.contains(evt.target);
|
|
118
|
+
if (!isInside && !preventCloseOnClickOutside) {
|
|
110
119
|
closeModal(evt);
|
|
111
120
|
}
|
|
112
121
|
}
|
|
@@ -115,7 +124,7 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
|
|
|
115
124
|
target: oldActiveNode,
|
|
116
125
|
relatedTarget: currentActiveNode
|
|
117
126
|
} = _ref3;
|
|
118
|
-
if (open && currentActiveNode && oldActiveNode) {
|
|
127
|
+
if (open && currentActiveNode && oldActiveNode && innerModal.current) {
|
|
119
128
|
const {
|
|
120
129
|
current: bodyNode
|
|
121
130
|
} = innerModal;
|
|
@@ -127,62 +136,46 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
|
|
|
127
136
|
} = endSentinel;
|
|
128
137
|
wrapFocus({
|
|
129
138
|
bodyNode,
|
|
130
|
-
startSentinelNode,
|
|
131
|
-
endSentinelNode,
|
|
139
|
+
startTrapNode: startSentinelNode,
|
|
140
|
+
endTrapNode: endSentinelNode,
|
|
132
141
|
currentActiveNode,
|
|
133
142
|
oldActiveNode,
|
|
134
|
-
selectorsFloatingMenus
|
|
143
|
+
selectorsFloatingMenus: selectorsFloatingMenus?.filter(Boolean)
|
|
135
144
|
});
|
|
136
145
|
}
|
|
137
146
|
}
|
|
138
147
|
function closeModal(evt) {
|
|
139
148
|
if (!onClose || onClose(evt) !== false) {
|
|
140
|
-
|
|
149
|
+
setIsOpen(false);
|
|
141
150
|
}
|
|
142
151
|
}
|
|
143
|
-
const modalClass = cx({
|
|
144
|
-
|
|
145
|
-
'is-visible': isOpen,
|
|
146
|
-
[customClassName]: customClassName,
|
|
147
|
-
[`${prefix}--modal--danger`]: danger
|
|
148
|
-
});
|
|
149
|
-
const containerClass = cx({
|
|
150
|
-
[`${prefix}--modal-container`]: true,
|
|
151
|
-
[`${prefix}--modal-container--${size}`]: size,
|
|
152
|
-
[`${prefix}--modal-container--full-width`]: isFullWidth,
|
|
153
|
-
[containerClassName]: containerClassName
|
|
154
|
-
});
|
|
152
|
+
const modalClass = cx(`${prefix}--modal`, isOpen && 'is-visible', danger && `${prefix}--modal--danger`, customClassName);
|
|
153
|
+
const containerClass = cx(`${prefix}--modal-container`, size && `${prefix}--modal-container--${size}`, isFullWidth && `${prefix}--modal-container--full-width`, containerClassName);
|
|
155
154
|
|
|
156
155
|
// Generate aria-label based on Modal Header label if one is not provided (L253)
|
|
157
156
|
let generatedAriaLabel;
|
|
158
157
|
const childrenWithProps = React__default.Children.toArray(children).map(child => {
|
|
159
|
-
switch (
|
|
160
|
-
case React__default.createElement(ModalHeader).type:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
158
|
+
switch (true) {
|
|
159
|
+
case isElement(child) && child.type === React__default.createElement(ModalHeader).type:
|
|
160
|
+
{
|
|
161
|
+
const el = child;
|
|
162
|
+
generatedAriaLabel = el.props.label;
|
|
163
|
+
return /*#__PURE__*/React__default.cloneElement(el, {
|
|
164
|
+
closeModal
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
case isElement(child) && child.type === React__default.createElement(ModalFooter).type:
|
|
168
|
+
{
|
|
169
|
+
const el = child;
|
|
170
|
+
return /*#__PURE__*/React__default.cloneElement(el, {
|
|
171
|
+
closeModal,
|
|
172
|
+
inputref: button
|
|
173
|
+
});
|
|
174
|
+
}
|
|
170
175
|
default:
|
|
171
176
|
return child;
|
|
172
177
|
}
|
|
173
178
|
});
|
|
174
|
-
useEffect(() => {
|
|
175
|
-
if (prevOpen !== isOpen) {
|
|
176
|
-
toggleClass(document.body, `${prefix}--body--with-modal-open`, isOpen);
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
useEffect(() => {
|
|
180
|
-
return () => toggleClass(document.body, `${prefix}--body--with-modal-open`, false);
|
|
181
|
-
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
182
|
-
|
|
183
|
-
useEffect(() => {
|
|
184
|
-
toggleClass(document.body, `${prefix}--body--with-modal-open`, open);
|
|
185
|
-
}, [open, prefix]);
|
|
186
179
|
useEffect(() => {
|
|
187
180
|
const focusButton = focusContainerElement => {
|
|
188
181
|
if (focusContainerElement) {
|
|
@@ -257,7 +250,7 @@ ComposedModal.propTypes = {
|
|
|
257
250
|
*/
|
|
258
251
|
danger: PropTypes.bool,
|
|
259
252
|
/**
|
|
260
|
-
* Specify whether
|
|
253
|
+
* Specify whether the Modal content should have any inner padding.
|
|
261
254
|
*/
|
|
262
255
|
isFullWidth: PropTypes.bool,
|
|
263
256
|
/**
|
|
@@ -290,9 +283,7 @@ ComposedModal.propTypes = {
|
|
|
290
283
|
size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg'])
|
|
291
284
|
};
|
|
292
285
|
ComposedModal.defaultProps = {
|
|
293
|
-
onKeyDown: () => {},
|
|
294
286
|
selectorPrimaryFocus: '[data-modal-primary-focus]'
|
|
295
287
|
};
|
|
296
|
-
var ComposedModal$1 = ComposedModal;
|
|
297
288
|
|
|
298
|
-
export { ModalBody, ComposedModal
|
|
289
|
+
export { ModalBody, ComposedModal as default };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, { type ReactNode, type MouseEvent, type Ref } from 'react';
|
|
2
|
+
interface SecondaryButtonProps {
|
|
3
|
+
buttonText: ReactNode;
|
|
4
|
+
onClick(evt: MouseEvent): void;
|
|
5
|
+
}
|
|
6
|
+
export interface SecondaryButtonSetProps {
|
|
7
|
+
closeModal(evt: MouseEvent): void;
|
|
8
|
+
onRequestClose(evt: MouseEvent): void;
|
|
9
|
+
secondaryButtonText?: string;
|
|
10
|
+
secondaryButtons?: [SecondaryButtonProps, SecondaryButtonProps];
|
|
11
|
+
secondaryClassName?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ModalFooterProps {
|
|
14
|
+
/**
|
|
15
|
+
* Pass in content that will be rendered in the Modal Footer
|
|
16
|
+
*/
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Specify a custom className to be applied to the Modal Footer container
|
|
20
|
+
*/
|
|
21
|
+
className?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Specify an optional function that is called whenever the modal is closed
|
|
24
|
+
*/
|
|
25
|
+
closeModal?(evt: MouseEvent): void;
|
|
26
|
+
/**
|
|
27
|
+
* Specify whether the primary button should be replaced with danger button.
|
|
28
|
+
* Note that this prop is not applied if you render primary/danger button by yourself
|
|
29
|
+
*/
|
|
30
|
+
danger?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The `ref` callback for the primary button.
|
|
33
|
+
*/
|
|
34
|
+
inputref?: Ref<HTMLButtonElement>;
|
|
35
|
+
/**
|
|
36
|
+
* Specify an optional function for when the modal is requesting to be
|
|
37
|
+
* closed
|
|
38
|
+
*/
|
|
39
|
+
onRequestClose?(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Specify an optional function for when the modal is requesting to be
|
|
42
|
+
* submitted
|
|
43
|
+
*/
|
|
44
|
+
onRequestSubmit?(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Specify whether the primary button should be disabled
|
|
47
|
+
*/
|
|
48
|
+
primaryButtonDisabled?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Specify the text for the primary button
|
|
51
|
+
*/
|
|
52
|
+
primaryButtonText?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Specify a custom className to be applied to the primary button
|
|
55
|
+
*/
|
|
56
|
+
primaryClassName?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Specify the text for the secondary button
|
|
59
|
+
*/
|
|
60
|
+
secondaryButtonText?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Specify an array of config objects for secondary buttons
|
|
63
|
+
*/
|
|
64
|
+
secondaryButtons?: [SecondaryButtonProps, SecondaryButtonProps];
|
|
65
|
+
/**
|
|
66
|
+
* Specify a custom className to be applied to the secondary button
|
|
67
|
+
*/
|
|
68
|
+
secondaryClassName?: string;
|
|
69
|
+
}
|
|
70
|
+
export declare const ModalFooter: React.ForwardRefExoticComponent<ModalFooterProps & React.RefAttributes<HTMLElement>>;
|
|
71
|
+
export {};
|
|
@@ -9,6 +9,7 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
|
|
|
9
9
|
import React__default from 'react';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import Button from '../Button/Button.js';
|
|
12
|
+
import '../Button/Button.Skeleton.js';
|
|
12
13
|
import ButtonSet from '../ButtonSet/ButtonSet.js';
|
|
13
14
|
import cx from 'classnames';
|
|
14
15
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
@@ -87,11 +88,7 @@ const ModalFooter = /*#__PURE__*/React__default.forwardRef(function ModalFooter(
|
|
|
87
88
|
...rest
|
|
88
89
|
} = _ref3;
|
|
89
90
|
const prefix = usePrefix();
|
|
90
|
-
const footerClass = cx({
|
|
91
|
-
[`${prefix}--modal-footer`]: true,
|
|
92
|
-
[customClassName]: customClassName,
|
|
93
|
-
[`${prefix}--modal-footer--three-button`]: Array.isArray(secondaryButtons) && secondaryButtons.length === 2
|
|
94
|
-
});
|
|
91
|
+
const footerClass = cx(`${prefix}--modal-footer`, customClassName, Array.isArray(secondaryButtons) && secondaryButtons.length === 2 ? `${prefix}--modal-footer--three-button` : null);
|
|
95
92
|
const secondaryButtonProps = {
|
|
96
93
|
closeModal,
|
|
97
94
|
secondaryButtons,
|
|
@@ -99,17 +96,21 @@ const ModalFooter = /*#__PURE__*/React__default.forwardRef(function ModalFooter(
|
|
|
99
96
|
secondaryClassName,
|
|
100
97
|
onRequestClose
|
|
101
98
|
};
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
return (
|
|
100
|
+
/*#__PURE__*/
|
|
101
|
+
// @ts-expect-error: Invalid derived types, will be fine once explicit types are added
|
|
102
|
+
React__default.createElement(ButtonSet, _extends({
|
|
103
|
+
className: footerClass
|
|
104
|
+
}, rest, {
|
|
105
|
+
ref: ref
|
|
106
|
+
}), /*#__PURE__*/React__default.createElement(SecondaryButtonSet, secondaryButtonProps), primaryButtonText && /*#__PURE__*/React__default.createElement(Button, {
|
|
107
|
+
onClick: onRequestSubmit,
|
|
108
|
+
className: primaryClassName,
|
|
109
|
+
disabled: primaryButtonDisabled,
|
|
110
|
+
kind: danger ? 'danger' : 'primary',
|
|
111
|
+
ref: inputref
|
|
112
|
+
}, primaryButtonText), children)
|
|
113
|
+
);
|
|
113
114
|
});
|
|
114
115
|
ModalFooter.propTypes = {
|
|
115
116
|
/**
|
|
@@ -132,6 +133,7 @@ ModalFooter.propTypes = {
|
|
|
132
133
|
/**
|
|
133
134
|
* The `ref` callback for the primary button.
|
|
134
135
|
*/
|
|
136
|
+
// @ts-expect-error: Invalid derived type
|
|
135
137
|
inputref: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
|
|
136
138
|
current: PropTypes.any
|
|
137
139
|
})]),
|
|
@@ -188,10 +190,11 @@ ModalFooter.propTypes = {
|
|
|
188
190
|
*/
|
|
189
191
|
secondaryClassName: PropTypes.string
|
|
190
192
|
};
|
|
193
|
+
const noop = () => {};
|
|
191
194
|
ModalFooter.defaultProps = {
|
|
192
|
-
onRequestClose:
|
|
193
|
-
onRequestSubmit:
|
|
194
|
-
closeModal:
|
|
195
|
+
onRequestClose: noop,
|
|
196
|
+
onRequestSubmit: noop,
|
|
197
|
+
closeModal: noop
|
|
195
198
|
};
|
|
196
199
|
|
|
197
200
|
export { ModalFooter };
|
|
@@ -0,0 +1,58 @@
|
|
|
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 React, { type ReactNode, type MouseEvent, type HTMLAttributes } from 'react';
|
|
8
|
+
type DivProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'>;
|
|
9
|
+
export interface ModalHeaderProps extends DivProps {
|
|
10
|
+
/**
|
|
11
|
+
* Provide an optional function to be called when the close button is
|
|
12
|
+
* clicked
|
|
13
|
+
*/
|
|
14
|
+
buttonOnClick?(event: MouseEvent): void;
|
|
15
|
+
/**
|
|
16
|
+
* Specify the content to be placed in the ModalHeader
|
|
17
|
+
*/
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Specify an optional className to be applied to the modal header
|
|
21
|
+
*/
|
|
22
|
+
className?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Specify an optional className to be applied to the modal close node
|
|
25
|
+
*/
|
|
26
|
+
closeClassName?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Specify an optional className to be applied to the modal close icon node
|
|
29
|
+
*/
|
|
30
|
+
closeIconClassName?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Provide an optional function to be called when the modal is closed
|
|
33
|
+
*/
|
|
34
|
+
closeModal?(event: MouseEvent): void;
|
|
35
|
+
/**
|
|
36
|
+
* Specify a description for the close icon that can be read by screen
|
|
37
|
+
* readers
|
|
38
|
+
*/
|
|
39
|
+
iconDescription?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Specify an optional label to be displayed
|
|
42
|
+
*/
|
|
43
|
+
label?: ReactNode;
|
|
44
|
+
/**
|
|
45
|
+
* Specify an optional className to be applied to the modal header label
|
|
46
|
+
*/
|
|
47
|
+
labelClassName?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Specify an optional title to be displayed
|
|
50
|
+
*/
|
|
51
|
+
title?: ReactNode;
|
|
52
|
+
/**
|
|
53
|
+
* Specify an optional className to be applied to the modal heading
|
|
54
|
+
*/
|
|
55
|
+
titleClassName?: string;
|
|
56
|
+
}
|
|
57
|
+
export declare const ModalHeader: React.ForwardRefExoticComponent<ModalHeaderProps & React.RefAttributes<HTMLDivElement>>;
|
|
58
|
+
export {};
|
|
@@ -29,29 +29,14 @@ const ModalHeader = /*#__PURE__*/React__default.forwardRef(function ModalHeader(
|
|
|
29
29
|
} = _ref;
|
|
30
30
|
const prefix = usePrefix();
|
|
31
31
|
function handleCloseButtonClick(evt) {
|
|
32
|
-
closeModal(evt);
|
|
33
|
-
buttonOnClick();
|
|
32
|
+
closeModal?.(evt);
|
|
33
|
+
buttonOnClick?.(evt);
|
|
34
34
|
}
|
|
35
|
-
const headerClass = cx({
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
39
|
-
const
|
|
40
|
-
[`${prefix}--modal-header__label ${prefix}--type-delta`]: true,
|
|
41
|
-
[labelClassName]: labelClassName
|
|
42
|
-
});
|
|
43
|
-
const titleClass = cx({
|
|
44
|
-
[`${prefix}--modal-header__heading ${prefix}--type-beta`]: true,
|
|
45
|
-
[titleClassName]: titleClassName
|
|
46
|
-
});
|
|
47
|
-
const closeClass = cx({
|
|
48
|
-
[`${prefix}--modal-close`]: true,
|
|
49
|
-
[closeClassName]: closeClassName
|
|
50
|
-
});
|
|
51
|
-
const closeIconClass = cx({
|
|
52
|
-
[`${prefix}--modal-close__icon`]: true,
|
|
53
|
-
[closeIconClassName]: closeIconClassName
|
|
54
|
-
});
|
|
35
|
+
const headerClass = cx(`${prefix}--modal-header`, customClassName);
|
|
36
|
+
const labelClass = cx(`${prefix}--modal-header__label ${prefix}--type-delta`, labelClassName);
|
|
37
|
+
const titleClass = cx(`${prefix}--modal-header__heading ${prefix}--type-beta`, titleClassName);
|
|
38
|
+
const closeClass = cx(`${prefix}--modal-close`, closeClassName);
|
|
39
|
+
const closeIconClass = cx(`${prefix}--modal-close__icon`, closeIconClassName);
|
|
55
40
|
return /*#__PURE__*/React__default.createElement("div", _extends({
|
|
56
41
|
className: headerClass
|
|
57
42
|
}, rest, {
|
|
@@ -120,9 +105,7 @@ ModalHeader.propTypes = {
|
|
|
120
105
|
titleClassName: PropTypes.string
|
|
121
106
|
};
|
|
122
107
|
ModalHeader.defaultProps = {
|
|
123
|
-
iconDescription: 'Close'
|
|
124
|
-
buttonOnClick: () => {},
|
|
125
|
-
closeModal: () => {}
|
|
108
|
+
iconDescription: 'Close'
|
|
126
109
|
};
|
|
127
110
|
|
|
128
111
|
export { ModalHeader };
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
export { default as ComposedModal, type ComposedModalProps, ModalBody, type ModalBodyProps, } from './ComposedModal';
|
|
8
|
+
export { ModalHeader, type ModalHeaderProps } from './ModalHeader';
|
|
9
|
+
export { ModalFooter, type ModalFooterProps } from './ModalFooter';
|
|
@@ -70,7 +70,18 @@ function ContainedList(_ref) {
|
|
|
70
70
|
max: 'xl'
|
|
71
71
|
},
|
|
72
72
|
className: `${prefix}--contained-list__action`
|
|
73
|
-
}, action)), children &&
|
|
73
|
+
}, action)), children &&
|
|
74
|
+
/*#__PURE__*/
|
|
75
|
+
/**
|
|
76
|
+
* Webkit removes implicit "list" semantics when "list-style-type: none" is set.
|
|
77
|
+
* Explicitly setting the "list" role ensures assistive technology in webkit
|
|
78
|
+
* browsers correctly announce the semantics.
|
|
79
|
+
*
|
|
80
|
+
* Ref https://bugs.webkit.org/show_bug.cgi?id=170179#c1
|
|
81
|
+
*/
|
|
82
|
+
// eslint-disable-next-line jsx-a11y/no-redundant-roles
|
|
83
|
+
React__default.createElement("ul", {
|
|
84
|
+
role: "list",
|
|
74
85
|
"aria-labelledby": labelId
|
|
75
86
|
}, isActionSearch ? filteredChildren : renderedChildren));
|
|
76
87
|
}
|