carbon-react 120.5.0 → 120.6.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.
@@ -7,5 +7,5 @@ declare const HiddenCurrentColorList: import("styled-components").StyledComponen
7
7
  displayName: string;
8
8
  }, any, {}, never>;
9
9
  declare const StyledAdvancedColorPickerPreview: import("styled-components").StyledComponent<"div", any, {}, never>;
10
- declare const DialogStyle: import("styled-components").StyledComponent<({ className, children, open, height, size, title, disableEscKey, subtitle, disableAutoFocus, focusFirstElement, focusableSelectors, onCancel, showCloseIcon, bespokeFocusTrap, disableClose, help, role, contentPadding, focusableContainers, ...rest }: import("../dialog/dialog.component").DialogProps) => import("react").JSX.Element, any, {}, never>;
10
+ declare const DialogStyle: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../dialog/dialog.component").DialogProps & import("react").RefAttributes<import("../dialog/dialog.component").DialogHandle>>, any, {}, never>;
11
11
  export { StyledAdvancedColorPickerWrapper, HiddenCurrentColorList, StyledAdvancedColorPickerCell, StyledAdvancedColorPickerPreview, DialogStyle, };
@@ -59,5 +59,9 @@ export interface DialogProps extends ModalProps, TagProps {
59
59
  /** an optional array of refs to containers whose content should also be reachable by tabbing from the dialog */
60
60
  focusableContainers?: CustomRefObject<HTMLElement>[];
61
61
  }
62
- export declare const Dialog: ({ className, children, open, height, size, title, disableEscKey, subtitle, disableAutoFocus, focusFirstElement, focusableSelectors, onCancel, showCloseIcon, bespokeFocusTrap, disableClose, help, role, contentPadding, focusableContainers, ...rest }: DialogProps) => React.JSX.Element;
62
+ export declare type DialogHandle = {
63
+ /** Programmatically focus on root container of Dialog. */
64
+ focus: () => void;
65
+ } | null;
66
+ export declare const Dialog: React.ForwardRefExoticComponent<DialogProps & React.RefAttributes<DialogHandle>>;
63
67
  export default Dialog;
@@ -1,5 +1,5 @@
1
1
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
- import React, { useRef, useEffect, useLayoutEffect, useCallback } from "react";
2
+ import React, { useRef, useEffect, useLayoutEffect, useCallback, useImperativeHandle, forwardRef } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import createGuid from "../../__internal__/utils/helpers/guid";
5
5
  import Modal from "../modal";
@@ -14,7 +14,7 @@ import useLocale from "../../hooks/__internal__/useLocale";
14
14
  import useIsStickyFooterForm from "../../hooks/__internal__/useIsStickyFooterForm";
15
15
  import useModalAria from "../../hooks/__internal__/useModalAria/useModalAria";
16
16
  const PADDING_VALUES = [0, 1, 2, 3, 4, 5, 6, 7, 8];
17
- export const Dialog = ({
17
+ const Dialog = /*#__PURE__*/forwardRef(({
18
18
  className,
19
19
  children,
20
20
  open,
@@ -35,9 +35,9 @@ export const Dialog = ({
35
35
  contentPadding = {},
36
36
  focusableContainers,
37
37
  ...rest
38
- }) => {
38
+ }, ref) => {
39
39
  const locale = useLocale();
40
- const dialogRef = useRef(null);
40
+ const containerRef = useRef(null);
41
41
  const innerContentRef = useRef(null);
42
42
  const titleRef = useRef(null);
43
43
  const listenersAdded = useRef(false);
@@ -48,16 +48,21 @@ export const Dialog = ({
48
48
  current: subtitleId
49
49
  } = useRef(createGuid());
50
50
  const hasStickyFooter = useIsStickyFooterForm(children);
51
- const isTopModal = useModalAria(dialogRef);
51
+ const isTopModal = useModalAria(containerRef);
52
+ useImperativeHandle(ref, () => ({
53
+ focus() {
54
+ containerRef.current?.focus();
55
+ }
56
+ }), []);
52
57
  const centerDialog = useCallback(() => {
53
58
  /* istanbul ignore if */
54
- if (!dialogRef.current) {
59
+ if (!containerRef.current) {
55
60
  return;
56
61
  }
57
62
  const {
58
63
  width: dialogWidth,
59
64
  height: dialogHeight
60
- } = dialogRef.current.getBoundingClientRect();
65
+ } = containerRef.current.getBoundingClientRect();
61
66
  let midPointY = window.innerHeight / 2;
62
67
  let midPointX = window.innerWidth / 2;
63
68
  midPointY -= dialogHeight / 2;
@@ -68,8 +73,8 @@ export const Dialog = ({
68
73
  if (midPointX < 0) {
69
74
  midPointX = 0;
70
75
  }
71
- dialogRef.current.style.top = `${midPointY}px`;
72
- dialogRef.current.style.left = `${midPointX}px`;
76
+ containerRef.current.style.top = `${midPointY}px`;
77
+ containerRef.current.style.left = `${midPointX}px`;
73
78
  }, []);
74
79
  useResizeObserver(innerContentRef, centerDialog, !open);
75
80
  const addListeners = useCallback(() => {
@@ -155,22 +160,81 @@ export const Dialog = ({
155
160
  focusFirstElement: focusFirstElement,
156
161
  bespokeTrap: bespokeFocusTrap,
157
162
  focusableSelectors: focusableSelectors,
158
- wrapperRef: dialogRef,
163
+ wrapperRef: containerRef,
159
164
  isOpen: open,
160
165
  additionalWrapperRefs: focusableContainers
161
166
  }, /*#__PURE__*/React.createElement(StyledDialog, _extends({
162
167
  "aria-modal": isTopModal ? true : undefined,
163
- ref: dialogRef,
168
+ ref: containerRef,
164
169
  topMargin: TOP_MARGIN
165
170
  }, dialogProps, {
166
171
  "data-component": "dialog",
167
172
  "data-element": "dialog",
168
173
  "data-role": rest["data-role"],
169
- role: role
174
+ role: role,
175
+ tabIndex: -1
170
176
  }, contentPadding), dialogTitle(), closeIcon(), /*#__PURE__*/React.createElement(StyledDialogContent, _extends({}, contentPadding, {
171
177
  hasStickyFooter: hasStickyFooter
172
178
  }), /*#__PURE__*/React.createElement(StyledDialogInnerContent, _extends({
173
179
  ref: innerContentRef
174
180
  }, contentPadding), children)))));
181
+ });
182
+ Dialog.propTypes = {
183
+ "aria-describedby": PropTypes.string,
184
+ "aria-label": PropTypes.string,
185
+ "aria-labelledby": PropTypes.string,
186
+ "ariaRole": PropTypes.string,
187
+ "bespokeFocusTrap": PropTypes.func,
188
+ "children": PropTypes.node,
189
+ "className": PropTypes.string,
190
+ "contentPadding": PropTypes.shape({
191
+ "p": PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8]),
192
+ "px": PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8]),
193
+ "py": PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8])
194
+ }),
195
+ "data-component": PropTypes.string,
196
+ "data-element": PropTypes.string,
197
+ "data-role": PropTypes.string,
198
+ "disableAutoFocus": PropTypes.bool,
199
+ "disableClose": PropTypes.bool,
200
+ "disableEscKey": PropTypes.bool,
201
+ "disableFocusTrap": PropTypes.bool,
202
+ "enableBackgroundUI": PropTypes.bool,
203
+ "focusableContainers": PropTypes.arrayOf(PropTypes.shape({
204
+ "current": function (props, propName) {
205
+ if (props[propName] == null) {
206
+ return null;
207
+ } else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
208
+ return new Error("Expected prop '" + propName + "' to be of type Element");
209
+ }
210
+ }
211
+ })),
212
+ "focusableSelectors": PropTypes.string,
213
+ "focusFirstElement": PropTypes.oneOfType([function (props, propName) {
214
+ if (props[propName] == null) {
215
+ return new Error("Prop '" + propName + "' is required but wasn't specified");
216
+ } else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
217
+ return new Error("Expected prop '" + propName + "' to be of type Element");
218
+ }
219
+ }, PropTypes.shape({
220
+ "current": function (props, propName) {
221
+ if (props[propName] == null) {
222
+ return null;
223
+ } else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
224
+ return new Error("Expected prop '" + propName + "' to be of type Element");
225
+ }
226
+ }
227
+ })]),
228
+ "height": PropTypes.string,
229
+ "help": PropTypes.string,
230
+ "onCancel": PropTypes.func,
231
+ "open": PropTypes.bool.isRequired,
232
+ "role": PropTypes.string,
233
+ "showCloseIcon": PropTypes.bool,
234
+ "size": PropTypes.oneOf(["auto", "extra-large", "extra-small", "large", "medium-large", "medium-small", "medium", "small"]),
235
+ "subtitle": PropTypes.string,
236
+ "timeout": PropTypes.number,
237
+ "title": PropTypes.node
175
238
  };
239
+ export { Dialog };
176
240
  export default Dialog;
@@ -1,3 +1,4 @@
1
1
  export { default } from "./dialog.component";
2
2
  export type { DialogProps } from "./dialog.component";
3
+ export type { DialogHandle } from "./dialog.component";
3
4
  export type { DialogSizes } from "./dialog.config";
@@ -7,5 +7,5 @@ declare const HiddenCurrentColorList: import("styled-components").StyledComponen
7
7
  displayName: string;
8
8
  }, any, {}, never>;
9
9
  declare const StyledAdvancedColorPickerPreview: import("styled-components").StyledComponent<"div", any, {}, never>;
10
- declare const DialogStyle: import("styled-components").StyledComponent<({ className, children, open, height, size, title, disableEscKey, subtitle, disableAutoFocus, focusFirstElement, focusableSelectors, onCancel, showCloseIcon, bespokeFocusTrap, disableClose, help, role, contentPadding, focusableContainers, ...rest }: import("../dialog/dialog.component").DialogProps) => import("react").JSX.Element, any, {}, never>;
10
+ declare const DialogStyle: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../dialog/dialog.component").DialogProps & import("react").RefAttributes<import("../dialog/dialog.component").DialogHandle>>, any, {}, never>;
11
11
  export { StyledAdvancedColorPickerWrapper, HiddenCurrentColorList, StyledAdvancedColorPickerCell, StyledAdvancedColorPickerPreview, DialogStyle, };
@@ -59,5 +59,9 @@ export interface DialogProps extends ModalProps, TagProps {
59
59
  /** an optional array of refs to containers whose content should also be reachable by tabbing from the dialog */
60
60
  focusableContainers?: CustomRefObject<HTMLElement>[];
61
61
  }
62
- export declare const Dialog: ({ className, children, open, height, size, title, disableEscKey, subtitle, disableAutoFocus, focusFirstElement, focusableSelectors, onCancel, showCloseIcon, bespokeFocusTrap, disableClose, help, role, contentPadding, focusableContainers, ...rest }: DialogProps) => React.JSX.Element;
62
+ export declare type DialogHandle = {
63
+ /** Programmatically focus on root container of Dialog. */
64
+ focus: () => void;
65
+ } | null;
66
+ export declare const Dialog: React.ForwardRefExoticComponent<DialogProps & React.RefAttributes<DialogHandle>>;
63
67
  export default Dialog;
@@ -23,7 +23,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
23
23
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
24
24
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
25
25
  const PADDING_VALUES = [0, 1, 2, 3, 4, 5, 6, 7, 8];
26
- const Dialog = ({
26
+ const Dialog = /*#__PURE__*/(0, _react.forwardRef)(({
27
27
  className,
28
28
  children,
29
29
  open,
@@ -44,9 +44,9 @@ const Dialog = ({
44
44
  contentPadding = {},
45
45
  focusableContainers,
46
46
  ...rest
47
- }) => {
47
+ }, ref) => {
48
48
  const locale = (0, _useLocale.default)();
49
- const dialogRef = (0, _react.useRef)(null);
49
+ const containerRef = (0, _react.useRef)(null);
50
50
  const innerContentRef = (0, _react.useRef)(null);
51
51
  const titleRef = (0, _react.useRef)(null);
52
52
  const listenersAdded = (0, _react.useRef)(false);
@@ -57,16 +57,21 @@ const Dialog = ({
57
57
  current: subtitleId
58
58
  } = (0, _react.useRef)((0, _guid.default)());
59
59
  const hasStickyFooter = (0, _useIsStickyFooterForm.default)(children);
60
- const isTopModal = (0, _useModalAria.default)(dialogRef);
60
+ const isTopModal = (0, _useModalAria.default)(containerRef);
61
+ (0, _react.useImperativeHandle)(ref, () => ({
62
+ focus() {
63
+ containerRef.current?.focus();
64
+ }
65
+ }), []);
61
66
  const centerDialog = (0, _react.useCallback)(() => {
62
67
  /* istanbul ignore if */
63
- if (!dialogRef.current) {
68
+ if (!containerRef.current) {
64
69
  return;
65
70
  }
66
71
  const {
67
72
  width: dialogWidth,
68
73
  height: dialogHeight
69
- } = dialogRef.current.getBoundingClientRect();
74
+ } = containerRef.current.getBoundingClientRect();
70
75
  let midPointY = window.innerHeight / 2;
71
76
  let midPointX = window.innerWidth / 2;
72
77
  midPointY -= dialogHeight / 2;
@@ -77,8 +82,8 @@ const Dialog = ({
77
82
  if (midPointX < 0) {
78
83
  midPointX = 0;
79
84
  }
80
- dialogRef.current.style.top = `${midPointY}px`;
81
- dialogRef.current.style.left = `${midPointX}px`;
85
+ containerRef.current.style.top = `${midPointY}px`;
86
+ containerRef.current.style.left = `${midPointX}px`;
82
87
  }, []);
83
88
  (0, _useResizeObserver.default)(innerContentRef, centerDialog, !open);
84
89
  const addListeners = (0, _react.useCallback)(() => {
@@ -164,24 +169,82 @@ const Dialog = ({
164
169
  focusFirstElement: focusFirstElement,
165
170
  bespokeTrap: bespokeFocusTrap,
166
171
  focusableSelectors: focusableSelectors,
167
- wrapperRef: dialogRef,
172
+ wrapperRef: containerRef,
168
173
  isOpen: open,
169
174
  additionalWrapperRefs: focusableContainers
170
175
  }, /*#__PURE__*/_react.default.createElement(_dialog.StyledDialog, _extends({
171
176
  "aria-modal": isTopModal ? true : undefined,
172
- ref: dialogRef,
177
+ ref: containerRef,
173
178
  topMargin: _dialog2.TOP_MARGIN
174
179
  }, dialogProps, {
175
180
  "data-component": "dialog",
176
181
  "data-element": "dialog",
177
182
  "data-role": rest["data-role"],
178
- role: role
183
+ role: role,
184
+ tabIndex: -1
179
185
  }, contentPadding), dialogTitle(), closeIcon(), /*#__PURE__*/_react.default.createElement(_dialog.StyledDialogContent, _extends({}, contentPadding, {
180
186
  hasStickyFooter: hasStickyFooter
181
187
  }), /*#__PURE__*/_react.default.createElement(_dialog.StyledDialogInnerContent, _extends({
182
188
  ref: innerContentRef
183
189
  }, contentPadding), children)))));
184
- };
190
+ });
185
191
  exports.Dialog = Dialog;
192
+ Dialog.propTypes = {
193
+ "aria-describedby": _propTypes.default.string,
194
+ "aria-label": _propTypes.default.string,
195
+ "aria-labelledby": _propTypes.default.string,
196
+ "ariaRole": _propTypes.default.string,
197
+ "bespokeFocusTrap": _propTypes.default.func,
198
+ "children": _propTypes.default.node,
199
+ "className": _propTypes.default.string,
200
+ "contentPadding": _propTypes.default.shape({
201
+ "p": _propTypes.default.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8]),
202
+ "px": _propTypes.default.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8]),
203
+ "py": _propTypes.default.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8])
204
+ }),
205
+ "data-component": _propTypes.default.string,
206
+ "data-element": _propTypes.default.string,
207
+ "data-role": _propTypes.default.string,
208
+ "disableAutoFocus": _propTypes.default.bool,
209
+ "disableClose": _propTypes.default.bool,
210
+ "disableEscKey": _propTypes.default.bool,
211
+ "disableFocusTrap": _propTypes.default.bool,
212
+ "enableBackgroundUI": _propTypes.default.bool,
213
+ "focusableContainers": _propTypes.default.arrayOf(_propTypes.default.shape({
214
+ "current": function (props, propName) {
215
+ if (props[propName] == null) {
216
+ return null;
217
+ } else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
218
+ return new Error("Expected prop '" + propName + "' to be of type Element");
219
+ }
220
+ }
221
+ })),
222
+ "focusableSelectors": _propTypes.default.string,
223
+ "focusFirstElement": _propTypes.default.oneOfType([function (props, propName) {
224
+ if (props[propName] == null) {
225
+ return new Error("Prop '" + propName + "' is required but wasn't specified");
226
+ } else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
227
+ return new Error("Expected prop '" + propName + "' to be of type Element");
228
+ }
229
+ }, _propTypes.default.shape({
230
+ "current": function (props, propName) {
231
+ if (props[propName] == null) {
232
+ return null;
233
+ } else if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {
234
+ return new Error("Expected prop '" + propName + "' to be of type Element");
235
+ }
236
+ }
237
+ })]),
238
+ "height": _propTypes.default.string,
239
+ "help": _propTypes.default.string,
240
+ "onCancel": _propTypes.default.func,
241
+ "open": _propTypes.default.bool.isRequired,
242
+ "role": _propTypes.default.string,
243
+ "showCloseIcon": _propTypes.default.bool,
244
+ "size": _propTypes.default.oneOf(["auto", "extra-large", "extra-small", "large", "medium-large", "medium-small", "medium", "small"]),
245
+ "subtitle": _propTypes.default.string,
246
+ "timeout": _propTypes.default.number,
247
+ "title": _propTypes.default.node
248
+ };
186
249
  var _default = Dialog;
187
250
  exports.default = _default;
@@ -1,3 +1,4 @@
1
1
  export { default } from "./dialog.component";
2
2
  export type { DialogProps } from "./dialog.component";
3
+ export type { DialogHandle } from "./dialog.component";
3
4
  export type { DialogSizes } from "./dialog.config";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "120.5.0",
3
+ "version": "120.6.0",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "files": [
6
6
  "lib",