@carbon/react 1.80.0 → 1.80.1

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.
@@ -17,14 +17,15 @@ import mergeRefs from '../../tools/mergeRefs.js';
17
17
  import cx from 'classnames';
18
18
  import toggleClass from '../../tools/toggleClass.js';
19
19
  import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy.js';
20
- import wrapFocus, { elementOrParentIsFloatingMenu } from '../../internal/wrapFocus.js';
20
+ import wrapFocus, { wrapFocusWithoutSentinels, elementOrParentIsFloatingMenu } from '../../internal/wrapFocus.js';
21
21
  import { usePrefix } from '../../internal/usePrefix.js';
22
- import { Escape } from '../../internal/keyboard/keys.js';
22
+ import { Escape, Tab } from '../../internal/keyboard/keys.js';
23
23
  import { match } from '../../internal/keyboard/match.js';
24
24
  import { useFeatureFlag } from '../FeatureFlags/index.js';
25
25
  import { composeEventHandlers } from '../../tools/events.js';
26
26
  import deprecate from '../../prop-types/deprecate.js';
27
27
  import { unstable__Dialog } from '../Dialog/index.js';
28
+ import { warning } from '../../internal/warning.js';
28
29
  import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.mjs.js';
29
30
 
30
31
  const ModalBody = /*#__PURE__*/React__default.forwardRef(function ModalBody(_ref, ref) {
@@ -121,9 +122,9 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
121
122
  const startSentinel = useRef(null);
122
123
  const endSentinel = useRef(null);
123
124
  const onMouseDownTarget = useRef(null);
124
- const enableDialogElement =
125
- // useFeatureFlag('enable-experimental-focus-wrap-without-sentinels') ||
126
- useFeatureFlag('enable-dialog-element');
125
+ const enableDialogElement = useFeatureFlag('enable-dialog-element');
126
+ const focusTrapWithoutSentinels = useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
127
+ process.env.NODE_ENV !== "production" ? warning(!(focusTrapWithoutSentinels && enableDialogElement), '`<Modal>` detected both `focusTrapWithoutSentinels` and ' + '`enableDialogElement` feature flags are enabled. The native dialog ' + 'element handles focus, so `enableDialogElement` must be off for ' + '`focusTrapWithoutSentinels` to have any effect.') : void 0;
127
128
 
128
129
  // Keep track of modal open/close state
129
130
  // and propagate it to the document.body
@@ -149,6 +150,13 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
149
150
  if (match(event, Escape)) {
150
151
  closeModal(event);
151
152
  }
153
+ if (focusTrapWithoutSentinels && open && match(event, Tab) && innerModal.current) {
154
+ wrapFocusWithoutSentinels({
155
+ containerNode: innerModal.current,
156
+ currentActiveNode: event.target,
157
+ event: event
158
+ });
159
+ }
152
160
  }
153
161
  onKeyDown?.(event);
154
162
  }
@@ -283,7 +291,7 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
283
291
  "aria-modal": "true",
284
292
  "aria-label": ariaLabel ? ariaLabel : generatedAriaLabel,
285
293
  "aria-labelledby": ariaLabelledBy
286
- }, /*#__PURE__*/React__default.createElement("button", {
294
+ }, !focusTrapWithoutSentinels && /*#__PURE__*/React__default.createElement("button", {
287
295
  type: "button",
288
296
  ref: startSentinel,
289
297
  className: `${prefix}--visually-hidden`
@@ -292,7 +300,7 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
292
300
  className: `${prefix}--modal-container-body`
293
301
  }, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React__default.createElement("div", {
294
302
  className: `${prefix}--modal--inner__decorator`
295
- }, normalizedDecorator) : '', childrenWithProps), /*#__PURE__*/React__default.createElement("button", {
303
+ }, normalizedDecorator) : '', childrenWithProps), !focusTrapWithoutSentinels && /*#__PURE__*/React__default.createElement("button", {
296
304
  type: "button",
297
305
  ref: endSentinel,
298
306
  className: `${prefix}--visually-hidden`
@@ -302,7 +310,7 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
302
310
  role: "presentation",
303
311
  ref: ref,
304
312
  "aria-hidden": !open,
305
- onBlur: !enableDialogElement ? handleBlur : () => {},
313
+ onBlur: !enableDialogElement && !focusTrapWithoutSentinels ? handleBlur : () => {},
306
314
  onClick: composeEventHandlers([rest?.onClick, handleOnClick]),
307
315
  onMouseDown: composeEventHandlers([rest?.onMouseDown, handleOnMouseDown]),
308
316
  onKeyDown: handleKeyDown,
@@ -17,11 +17,11 @@ import ButtonSet from '../ButtonSet/ButtonSet.js';
17
17
  import InlineLoading from '../InlineLoading/InlineLoading.js';
18
18
  import { Layer } from '../Layer/index.js';
19
19
  import requiredIfGivenPropIsTruthy from '../../prop-types/requiredIfGivenPropIsTruthy.js';
20
- import wrapFocus, { elementOrParentIsFloatingMenu } from '../../internal/wrapFocus.js';
20
+ import wrapFocus, { wrapFocusWithoutSentinels, elementOrParentIsFloatingMenu } from '../../internal/wrapFocus.js';
21
21
  import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
22
22
  import { useId } from '../../internal/useId.js';
23
23
  import { usePrefix } from '../../internal/usePrefix.js';
24
- import { Escape, Enter } from '../../internal/keyboard/keys.js';
24
+ import { Escape, Enter, Tab } from '../../internal/keyboard/keys.js';
25
25
  import { match } from '../../internal/keyboard/match.js';
26
26
  import { IconButton } from '../IconButton/index.js';
27
27
  import { noopFn } from '../../internal/noopFn.js';
@@ -30,6 +30,7 @@ import { useFeatureFlag } from '../FeatureFlags/index.js';
30
30
  import { composeEventHandlers } from '../../tools/events.js';
31
31
  import deprecate from '../../prop-types/deprecate.js';
32
32
  import { unstable__Dialog } from '../Dialog/index.js';
33
+ import { warning } from '../../internal/warning.js';
33
34
  import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.mjs.js';
34
35
  import { Text } from '../Text/Text.js';
35
36
 
@@ -87,7 +88,9 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
87
88
  [`${prefix}--btn--loading`]: loadingStatus !== 'inactive'
88
89
  });
89
90
  const loadingActive = loadingStatus !== 'inactive';
90
- const enableDialogElement = useFeatureFlag('enable-experimental-focus-wrap-without-sentinels') || useFeatureFlag('enable-dialog-element');
91
+ const focusTrapWithoutSentinels = useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
92
+ const enableDialogElement = useFeatureFlag('enable-dialog-element');
93
+ process.env.NODE_ENV !== "production" ? warning(!(focusTrapWithoutSentinels && enableDialogElement), '`<Modal>` detected both `focusTrapWithoutSentinels` and ' + '`enableDialogElement` feature flags are enabled. The native dialog ' + 'element handles focus, so `enableDialogElement` must be off for ' + '`focusTrapWithoutSentinels` to have any effect.') : void 0;
91
94
  function isCloseButton(element) {
92
95
  return !onSecondarySubmit && element === secondaryButton.current || element.classList.contains(modalCloseButtonClass);
93
96
  }
@@ -100,6 +103,15 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
100
103
  if (match(evt, Enter) && shouldSubmitOnEnter && !isCloseButton(evt.target)) {
101
104
  onRequestSubmit(evt);
102
105
  }
106
+ if (focusTrapWithoutSentinels && !enableDialogElement && match(evt, Tab) && innerModal.current) {
107
+ wrapFocusWithoutSentinels({
108
+ containerNode: innerModal.current,
109
+ currentActiveNode: evt.target,
110
+ // TODO: Delete type assertion following util rewrite.
111
+ // https://github.com/carbon-design-system/carbon/pull/18913
112
+ event: evt
113
+ });
114
+ }
103
115
  }
104
116
  }
105
117
  function handleOnClick(evt) {
@@ -326,7 +338,7 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
326
338
  iconDescription: loadingIconDescription,
327
339
  className: `${prefix}--inline-loading--btn`,
328
340
  onSuccess: onLoadingSuccess
329
- })))) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, !enableDialogElement && /*#__PURE__*/React__default.createElement("span", {
341
+ })))) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, !enableDialogElement && !focusTrapWithoutSentinels && /*#__PURE__*/React__default.createElement("span", {
330
342
  ref: startTrap,
331
343
  tabIndex: 0,
332
344
  role: "link",
@@ -385,7 +397,7 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
385
397
  iconDescription: loadingIconDescription,
386
398
  className: `${prefix}--inline-loading--btn`,
387
399
  onSuccess: onLoadingSuccess
388
- })))), !enableDialogElement && /*#__PURE__*/React__default.createElement("span", {
400
+ })))), !enableDialogElement && !focusTrapWithoutSentinels && /*#__PURE__*/React__default.createElement("span", {
389
401
  ref: endTrap,
390
402
  tabIndex: 0,
391
403
  role: "link",
@@ -29,6 +29,7 @@ var index$1 = require('../FeatureFlags/index.js');
29
29
  var events = require('../../tools/events.js');
30
30
  var deprecate = require('../../prop-types/deprecate.js');
31
31
  var index$2 = require('../Dialog/index.js');
32
+ var warning = require('../../internal/warning.js');
32
33
  var debounce = require('../../node_modules/es-toolkit/dist/compat/function/debounce.mjs.js');
33
34
 
34
35
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -131,9 +132,9 @@ const ComposedModal = /*#__PURE__*/React__default["default"].forwardRef(function
131
132
  const startSentinel = React.useRef(null);
132
133
  const endSentinel = React.useRef(null);
133
134
  const onMouseDownTarget = React.useRef(null);
134
- const enableDialogElement =
135
- // useFeatureFlag('enable-experimental-focus-wrap-without-sentinels') ||
136
- index$1.useFeatureFlag('enable-dialog-element');
135
+ const enableDialogElement = index$1.useFeatureFlag('enable-dialog-element');
136
+ const focusTrapWithoutSentinels = index$1.useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
137
+ process.env.NODE_ENV !== "production" ? warning.warning(!(focusTrapWithoutSentinels && enableDialogElement), '`<Modal>` detected both `focusTrapWithoutSentinels` and ' + '`enableDialogElement` feature flags are enabled. The native dialog ' + 'element handles focus, so `enableDialogElement` must be off for ' + '`focusTrapWithoutSentinels` to have any effect.') : void 0;
137
138
 
138
139
  // Keep track of modal open/close state
139
140
  // and propagate it to the document.body
@@ -159,6 +160,13 @@ const ComposedModal = /*#__PURE__*/React__default["default"].forwardRef(function
159
160
  if (match.match(event, keys.Escape)) {
160
161
  closeModal(event);
161
162
  }
163
+ if (focusTrapWithoutSentinels && open && match.match(event, keys.Tab) && innerModal.current) {
164
+ wrapFocus.wrapFocusWithoutSentinels({
165
+ containerNode: innerModal.current,
166
+ currentActiveNode: event.target,
167
+ event: event
168
+ });
169
+ }
162
170
  }
163
171
  onKeyDown?.(event);
164
172
  }
@@ -293,7 +301,7 @@ const ComposedModal = /*#__PURE__*/React__default["default"].forwardRef(function
293
301
  "aria-modal": "true",
294
302
  "aria-label": ariaLabel ? ariaLabel : generatedAriaLabel,
295
303
  "aria-labelledby": ariaLabelledBy
296
- }, /*#__PURE__*/React__default["default"].createElement("button", {
304
+ }, !focusTrapWithoutSentinels && /*#__PURE__*/React__default["default"].createElement("button", {
297
305
  type: "button",
298
306
  ref: startSentinel,
299
307
  className: `${prefix}--visually-hidden`
@@ -302,7 +310,7 @@ const ComposedModal = /*#__PURE__*/React__default["default"].forwardRef(function
302
310
  className: `${prefix}--modal-container-body`
303
311
  }, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React__default["default"].createElement("div", {
304
312
  className: `${prefix}--modal--inner__decorator`
305
- }, normalizedDecorator) : '', childrenWithProps), /*#__PURE__*/React__default["default"].createElement("button", {
313
+ }, normalizedDecorator) : '', childrenWithProps), !focusTrapWithoutSentinels && /*#__PURE__*/React__default["default"].createElement("button", {
306
314
  type: "button",
307
315
  ref: endSentinel,
308
316
  className: `${prefix}--visually-hidden`
@@ -312,7 +320,7 @@ const ComposedModal = /*#__PURE__*/React__default["default"].forwardRef(function
312
320
  role: "presentation",
313
321
  ref: ref,
314
322
  "aria-hidden": !open,
315
- onBlur: !enableDialogElement ? handleBlur : () => {},
323
+ onBlur: !enableDialogElement && !focusTrapWithoutSentinels ? handleBlur : () => {},
316
324
  onClick: events.composeEventHandlers([rest?.onClick, handleOnClick]),
317
325
  onMouseDown: events.composeEventHandlers([rest?.onMouseDown, handleOnMouseDown]),
318
326
  onKeyDown: handleKeyDown,
@@ -34,6 +34,7 @@ var index = require('../FeatureFlags/index.js');
34
34
  var events = require('../../tools/events.js');
35
35
  var deprecate = require('../../prop-types/deprecate.js');
36
36
  var index$1 = require('../Dialog/index.js');
37
+ var warning = require('../../internal/warning.js');
37
38
  var debounce = require('../../node_modules/es-toolkit/dist/compat/function/debounce.mjs.js');
38
39
  var Text = require('../Text/Text.js');
39
40
 
@@ -97,7 +98,9 @@ const Modal = /*#__PURE__*/React__default["default"].forwardRef(function Modal(_
97
98
  [`${prefix}--btn--loading`]: loadingStatus !== 'inactive'
98
99
  });
99
100
  const loadingActive = loadingStatus !== 'inactive';
100
- const enableDialogElement = index.useFeatureFlag('enable-experimental-focus-wrap-without-sentinels') || index.useFeatureFlag('enable-dialog-element');
101
+ const focusTrapWithoutSentinels = index.useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
102
+ const enableDialogElement = index.useFeatureFlag('enable-dialog-element');
103
+ process.env.NODE_ENV !== "production" ? warning.warning(!(focusTrapWithoutSentinels && enableDialogElement), '`<Modal>` detected both `focusTrapWithoutSentinels` and ' + '`enableDialogElement` feature flags are enabled. The native dialog ' + 'element handles focus, so `enableDialogElement` must be off for ' + '`focusTrapWithoutSentinels` to have any effect.') : void 0;
101
104
  function isCloseButton(element) {
102
105
  return !onSecondarySubmit && element === secondaryButton.current || element.classList.contains(modalCloseButtonClass);
103
106
  }
@@ -110,6 +113,15 @@ const Modal = /*#__PURE__*/React__default["default"].forwardRef(function Modal(_
110
113
  if (match.match(evt, keys.Enter) && shouldSubmitOnEnter && !isCloseButton(evt.target)) {
111
114
  onRequestSubmit(evt);
112
115
  }
116
+ if (focusTrapWithoutSentinels && !enableDialogElement && match.match(evt, keys.Tab) && innerModal.current) {
117
+ wrapFocus.wrapFocusWithoutSentinels({
118
+ containerNode: innerModal.current,
119
+ currentActiveNode: evt.target,
120
+ // TODO: Delete type assertion following util rewrite.
121
+ // https://github.com/carbon-design-system/carbon/pull/18913
122
+ event: evt
123
+ });
124
+ }
113
125
  }
114
126
  }
115
127
  function handleOnClick(evt) {
@@ -336,7 +348,7 @@ const Modal = /*#__PURE__*/React__default["default"].forwardRef(function Modal(_
336
348
  iconDescription: loadingIconDescription,
337
349
  className: `${prefix}--inline-loading--btn`,
338
350
  onSuccess: onLoadingSuccess
339
- })))) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, !enableDialogElement && /*#__PURE__*/React__default["default"].createElement("span", {
351
+ })))) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, !enableDialogElement && !focusTrapWithoutSentinels && /*#__PURE__*/React__default["default"].createElement("span", {
340
352
  ref: startTrap,
341
353
  tabIndex: 0,
342
354
  role: "link",
@@ -395,7 +407,7 @@ const Modal = /*#__PURE__*/React__default["default"].forwardRef(function Modal(_
395
407
  iconDescription: loadingIconDescription,
396
408
  className: `${prefix}--inline-loading--btn`,
397
409
  onSuccess: onLoadingSuccess
398
- })))), !enableDialogElement && /*#__PURE__*/React__default["default"].createElement("span", {
410
+ })))), !enableDialogElement && !focusTrapWithoutSentinels && /*#__PURE__*/React__default["default"].createElement("span", {
399
411
  ref: endTrap,
400
412
  tabIndex: 0,
401
413
  role: "link",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/react",
3
3
  "description": "React components for the Carbon Design System",
4
- "version": "1.80.0",
4
+ "version": "1.80.1",
5
5
  "license": "Apache-2.0",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -55,7 +55,7 @@
55
55
  "@carbon/feature-flags": "^0.26.0",
56
56
  "@carbon/icons-react": "^11.58.0",
57
57
  "@carbon/layout": "^11.32.0",
58
- "@carbon/styles": "^1.79.0",
58
+ "@carbon/styles": "^1.79.1",
59
59
  "@floating-ui/react": "^0.27.4",
60
60
  "@ibm/telemetry-js": "^1.5.0",
61
61
  "classnames": "2.5.1",
@@ -147,5 +147,5 @@
147
147
  "**/*.scss",
148
148
  "**/*.css"
149
149
  ],
150
- "gitHead": "7c4674649e1a5bd1367d99797df86cdc338eff6e"
150
+ "gitHead": "1fcbf602a0c0a9e33987b3b63e7a7a8b39af47d0"
151
151
  }