@carbon/react 1.31.3 → 1.32.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.
Files changed (182) hide show
  1. package/README.md +1 -1
  2. package/es/components/Accordion/Accordion.Skeleton.d.ts +64 -0
  3. package/es/components/Accordion/Accordion.Skeleton.js +3 -3
  4. package/es/components/Accordion/Accordion.d.ts +65 -0
  5. package/es/components/Accordion/Accordion.js +5 -6
  6. package/es/components/Accordion/AccordionItem.d.ts +105 -0
  7. package/es/components/Accordion/AccordionItem.js +12 -9
  8. package/es/components/Accordion/AccordionProvider.d.ts +20 -0
  9. package/es/components/Accordion/AccordionProvider.js +25 -0
  10. package/es/components/Accordion/index.d.ts +11 -0
  11. package/es/components/Button/Button.Skeleton.d.ts +28 -0
  12. package/es/components/Button/Button.Skeleton.js +5 -3
  13. package/es/components/Button/Button.d.ts +72 -0
  14. package/es/components/Button/Button.js +13 -10
  15. package/es/components/Button/index.d.ts +11 -0
  16. package/es/components/Button/index.js +2 -1
  17. package/es/components/ButtonSet/ButtonSet.d.ts +17 -0
  18. package/es/components/ButtonSet/ButtonSet.js +1 -2
  19. package/es/components/ButtonSet/index.d.ts +9 -0
  20. package/es/components/CodeSnippet/CodeSnippet.js +1 -0
  21. package/es/components/ComboButton/index.js +1 -0
  22. package/es/components/ComposedModal/ComposedModal.d.ts +70 -0
  23. package/es/components/ComposedModal/ComposedModal.js +58 -67
  24. package/es/components/ComposedModal/ModalFooter.d.ts +71 -0
  25. package/es/components/ComposedModal/ModalFooter.js +22 -19
  26. package/es/components/ComposedModal/ModalHeader.d.ts +58 -0
  27. package/es/components/ComposedModal/ModalHeader.js +8 -25
  28. package/es/components/ComposedModal/index.d.ts +9 -0
  29. package/es/components/ContainedList/ContainedList.js +12 -1
  30. package/es/components/ContentSwitcher/ContentSwitcher.d.ts +109 -0
  31. package/es/components/ContentSwitcher/ContentSwitcher.js +14 -6
  32. package/es/components/DangerButton/DangerButton.d.ts +9 -0
  33. package/es/components/DangerButton/DangerButton.js +2 -2
  34. package/es/components/DangerButton/index.d.ts +9 -0
  35. package/es/components/DataTable/TableBatchAction.js +1 -0
  36. package/es/components/DataTable/TableBatchActions.js +1 -0
  37. package/es/components/DataTable/TableBody.d.ts +29 -0
  38. package/es/components/DataTable/TableBody.js +2 -3
  39. package/es/components/DataTable/TableContainer.d.ts +51 -0
  40. package/es/components/DataTable/TableContainer.js +3 -4
  41. package/es/components/DataTable/TableExpandHeader.d.ts +86 -0
  42. package/es/components/DataTable/TableExpandHeader.js +4 -5
  43. package/es/components/DatePicker/plugins/fixEventsPlugin.js +12 -16
  44. package/es/components/Dropdown/Dropdown.js +1 -0
  45. package/es/components/FluidTextInput/FluidTextInput.js +1 -0
  46. package/es/components/FormGroup/FormGroup.d.ts +80 -0
  47. package/es/components/IconButton/index.js +3 -2
  48. package/es/components/Layout/index.d.ts +74 -0
  49. package/es/components/Layout/index.js +14 -5
  50. package/es/components/Link/Link.d.ts +2 -2
  51. package/es/components/Link/Link.js +2 -1
  52. package/es/components/MenuButton/index.js +1 -0
  53. package/es/components/Modal/Modal.js +1 -0
  54. package/es/components/ModalWrapper/ModalWrapper.js +1 -0
  55. package/es/components/Notification/Notification.d.ts +531 -0
  56. package/es/components/Notification/Notification.js +40 -6
  57. package/es/components/Notification/index.d.ts +7 -0
  58. package/es/components/PrimaryButton/PrimaryButton.js +1 -0
  59. package/es/components/SecondaryButton/SecondaryButton.js +1 -0
  60. package/es/components/Select/Select.d.ts +1 -1
  61. package/es/components/SkeletonText/SkeletonText.d.ts +61 -0
  62. package/es/components/SkeletonText/SkeletonText.js +15 -17
  63. package/es/components/SkeletonText/index.d.ts +9 -0
  64. package/es/components/Switch/Switch.d.ts +56 -0
  65. package/es/components/Switch/Switch.js +4 -4
  66. package/es/components/Tab/index.d.ts +9 -0
  67. package/es/components/TabContent/TabContent.d.ts +40 -0
  68. package/es/components/TabContent/TabContent.js +6 -12
  69. package/es/components/TabContent/index.d.ts +10 -0
  70. package/es/components/Tabs/Tabs.Skeleton.d.ts +33 -0
  71. package/es/components/Tabs/Tabs.Skeleton.js +2 -2
  72. package/es/components/Tabs/Tabs.d.ts +303 -0
  73. package/es/components/Tabs/Tabs.js +136 -95
  74. package/es/components/Tabs/index.d.ts +10 -0
  75. package/es/components/Tabs/usePressable.js +11 -0
  76. package/es/components/TextInput/ControlledPasswordInput.d.ts +90 -0
  77. package/es/components/TextInput/ControlledPasswordInput.js +5 -6
  78. package/es/components/Tile/Tile.d.ts +153 -0
  79. package/es/components/Tile/Tile.js +62 -74
  80. package/es/components/Tile/index.d.ts +7 -0
  81. package/es/components/Toggle/Toggle.Skeleton.d.ts +3 -47
  82. package/es/components/Toggle/Toggle.Skeleton.js +24 -64
  83. package/es/components/Toggle/Toggle.js +1 -1
  84. package/es/components/UIShell/HeaderGlobalAction.js +1 -0
  85. package/es/components/UIShell/SideNav.d.ts +1 -1
  86. package/es/index.js +16 -16
  87. package/es/internal/keyboard/match.js +2 -2
  88. package/es/internal/useControllableState.js +2 -2
  89. package/es/internal/wrapFocus.js +6 -6
  90. package/es/prop-types/requiredIfGivenPropIsTruthy.js +1 -1
  91. package/es/prop-types/types.js +3 -0
  92. package/lib/components/Accordion/Accordion.Skeleton.d.ts +64 -0
  93. package/lib/components/Accordion/Accordion.Skeleton.js +3 -3
  94. package/lib/components/Accordion/Accordion.d.ts +65 -0
  95. package/lib/components/Accordion/Accordion.js +5 -6
  96. package/lib/components/Accordion/AccordionItem.d.ts +105 -0
  97. package/lib/components/Accordion/AccordionItem.js +11 -8
  98. package/lib/components/Accordion/AccordionProvider.d.ts +20 -0
  99. package/lib/components/Accordion/AccordionProvider.js +34 -0
  100. package/lib/components/Accordion/index.d.ts +11 -0
  101. package/lib/components/Button/Button.Skeleton.d.ts +28 -0
  102. package/lib/components/Button/Button.Skeleton.js +5 -3
  103. package/lib/components/Button/Button.d.ts +72 -0
  104. package/lib/components/Button/Button.js +18 -11
  105. package/lib/components/Button/index.d.ts +11 -0
  106. package/lib/components/Button/index.js +6 -0
  107. package/lib/components/ButtonSet/ButtonSet.d.ts +17 -0
  108. package/lib/components/ButtonSet/ButtonSet.js +1 -2
  109. package/lib/components/ButtonSet/index.d.ts +9 -0
  110. package/lib/components/CodeSnippet/CodeSnippet.js +1 -0
  111. package/lib/components/ComboButton/index.js +1 -0
  112. package/lib/components/ComposedModal/ComposedModal.d.ts +70 -0
  113. package/lib/components/ComposedModal/ComposedModal.js +58 -67
  114. package/lib/components/ComposedModal/ModalFooter.d.ts +71 -0
  115. package/lib/components/ComposedModal/ModalFooter.js +22 -19
  116. package/lib/components/ComposedModal/ModalHeader.d.ts +58 -0
  117. package/lib/components/ComposedModal/ModalHeader.js +8 -25
  118. package/lib/components/ComposedModal/index.d.ts +9 -0
  119. package/lib/components/ContainedList/ContainedList.js +12 -1
  120. package/lib/components/ContentSwitcher/ContentSwitcher.d.ts +109 -0
  121. package/lib/components/ContentSwitcher/ContentSwitcher.js +14 -6
  122. package/lib/components/DangerButton/DangerButton.d.ts +9 -0
  123. package/lib/components/DangerButton/DangerButton.js +2 -2
  124. package/lib/components/DangerButton/index.d.ts +9 -0
  125. package/lib/components/DataTable/TableBatchAction.js +1 -0
  126. package/lib/components/DataTable/TableBatchActions.js +1 -0
  127. package/lib/components/DataTable/TableBody.d.ts +29 -0
  128. package/lib/components/DataTable/TableBody.js +3 -4
  129. package/lib/components/DataTable/TableContainer.d.ts +51 -0
  130. package/lib/components/DataTable/TableContainer.js +3 -4
  131. package/lib/components/DataTable/TableExpandHeader.d.ts +86 -0
  132. package/lib/components/DataTable/TableExpandHeader.js +4 -5
  133. package/lib/components/DatePicker/plugins/fixEventsPlugin.js +12 -16
  134. package/lib/components/Dropdown/Dropdown.js +1 -0
  135. package/lib/components/FluidTextInput/FluidTextInput.js +1 -0
  136. package/lib/components/FormGroup/FormGroup.d.ts +80 -0
  137. package/lib/components/IconButton/index.js +3 -2
  138. package/lib/components/Layout/index.d.ts +74 -0
  139. package/lib/components/Layout/index.js +14 -5
  140. package/lib/components/Link/Link.d.ts +2 -2
  141. package/lib/components/Link/Link.js +2 -1
  142. package/lib/components/MenuButton/index.js +1 -0
  143. package/lib/components/Modal/Modal.js +1 -0
  144. package/lib/components/ModalWrapper/ModalWrapper.js +1 -0
  145. package/lib/components/Notification/Notification.d.ts +531 -0
  146. package/lib/components/Notification/Notification.js +40 -6
  147. package/lib/components/Notification/index.d.ts +7 -0
  148. package/lib/components/PrimaryButton/PrimaryButton.js +1 -0
  149. package/lib/components/SecondaryButton/SecondaryButton.js +1 -0
  150. package/lib/components/Select/Select.d.ts +1 -1
  151. package/lib/components/SkeletonText/SkeletonText.d.ts +61 -0
  152. package/lib/components/SkeletonText/SkeletonText.js +15 -17
  153. package/lib/components/SkeletonText/index.d.ts +9 -0
  154. package/lib/components/Switch/Switch.d.ts +56 -0
  155. package/lib/components/Switch/Switch.js +4 -4
  156. package/lib/components/Tab/index.d.ts +9 -0
  157. package/lib/components/TabContent/TabContent.d.ts +40 -0
  158. package/lib/components/TabContent/TabContent.js +6 -12
  159. package/lib/components/TabContent/index.d.ts +10 -0
  160. package/lib/components/Tabs/Tabs.Skeleton.d.ts +33 -0
  161. package/lib/components/Tabs/Tabs.Skeleton.js +2 -2
  162. package/lib/components/Tabs/Tabs.d.ts +303 -0
  163. package/lib/components/Tabs/Tabs.js +135 -94
  164. package/lib/components/Tabs/index.d.ts +10 -0
  165. package/lib/components/Tabs/usePressable.js +11 -0
  166. package/lib/components/TextInput/ControlledPasswordInput.d.ts +90 -0
  167. package/lib/components/TextInput/ControlledPasswordInput.js +5 -6
  168. package/lib/components/Tile/Tile.d.ts +153 -0
  169. package/lib/components/Tile/Tile.js +62 -74
  170. package/lib/components/Tile/index.d.ts +7 -0
  171. package/lib/components/Toggle/Toggle.Skeleton.d.ts +3 -47
  172. package/lib/components/Toggle/Toggle.Skeleton.js +22 -62
  173. package/lib/components/Toggle/Toggle.js +1 -1
  174. package/lib/components/UIShell/HeaderGlobalAction.js +1 -0
  175. package/lib/components/UIShell/SideNav.d.ts +1 -1
  176. package/lib/index.js +51 -47
  177. package/lib/internal/keyboard/match.js +2 -2
  178. package/lib/internal/useControllableState.js +2 -2
  179. package/lib/internal/wrapFocus.js +6 -6
  180. package/lib/prop-types/requiredIfGivenPropIsTruthy.js +1 -1
  181. package/lib/prop-types/types.js +3 -0
  182. 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, setisOpen] = useState(open);
89
- const [prevOpen, setPrevOpen] = useState(open);
90
- const innerModal = useRef();
91
- const button = useRef();
92
- const startSentinel = useRef();
93
- const endSentinel = useRef();
94
- if (open !== prevOpen) {
95
- setisOpen(open);
96
- setPrevOpen(open);
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
- // Esc key
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
- if (!innerModal.current.contains(evt.target) && preventCloseOnClickOutside) {
107
- return;
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
- setisOpen(false);
149
+ setIsOpen(false);
141
150
  }
142
151
  }
143
- const modalClass = cx({
144
- [`${prefix}--modal`]: true,
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 (child.type) {
160
- case React__default.createElement(ModalHeader).type:
161
- generatedAriaLabel = child.props.label;
162
- return /*#__PURE__*/React__default.cloneElement(child, {
163
- closeModal: closeModal
164
- });
165
- case React__default.createElement(ModalFooter).type:
166
- return /*#__PURE__*/React__default.cloneElement(child, {
167
- closeModal: closeModal,
168
- inputref: button
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 or not the Modal content should have any inner padding.
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$1 as default };
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 /*#__PURE__*/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);
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
- [`${prefix}--modal-header`]: true,
37
- [customClassName]: customClassName
38
- });
39
- const labelClass = cx({
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 && /*#__PURE__*/React__default.createElement("ul", {
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
  }