@carbon/react 1.115.0-rc.0 → 1.115.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 (76) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1019 -984
  2. package/es/components/Accordion/AccordionItem.d.ts +5 -0
  3. package/es/components/Accordion/AccordionItem.js +0 -6
  4. package/es/components/ComboBox/ComboBox.js +2 -2
  5. package/es/components/ComposedModal/ComposedModal.js +2 -2
  6. package/es/components/ContentSwitcher/ContentSwitcher.js +2 -2
  7. package/es/components/DatePicker/DatePicker.js +2 -2
  8. package/es/components/FileUploader/FileUploader.js +1 -1
  9. package/es/components/FileUploader/FileUploaderButton.js +2 -2
  10. package/es/components/FileUploader/FileUploaderDropContainer.js +2 -2
  11. package/es/components/FileUploader/FileUploaderItem.js +2 -2
  12. package/es/components/Loading/Loading.js +82 -2
  13. package/es/components/Menu/Menu.js +2 -2
  14. package/es/components/Menu/MenuItem.js +2 -2
  15. package/es/components/Modal/Modal.js +3 -3
  16. package/es/components/MultiSelect/FilterableMultiSelect.js +2 -2
  17. package/es/components/MultiSelect/MultiSelect.js +2 -2
  18. package/es/components/Notification/Notification.js +2 -2
  19. package/es/components/NumberInput/NumberInput.js +2 -2
  20. package/es/components/OverflowMenu/OverflowMenu.js +2 -2
  21. package/es/components/OverflowMenuItem/OverflowMenuItem.js +1 -1
  22. package/es/components/Pagination/Pagination.d.ts +1 -1
  23. package/es/components/Pagination/Pagination.js +52 -53
  24. package/es/components/Popover/index.js +1 -1
  25. package/es/components/RadioTile/RadioTile.js +2 -2
  26. package/es/components/Search/Search.js +2 -2
  27. package/es/components/Slider/Slider.js +2 -2
  28. package/es/components/Tabs/Tabs.js +2 -2
  29. package/es/components/Tile/Tile.js +2 -2
  30. package/es/components/Toggletip/index.js +2 -2
  31. package/es/components/Tooltip/DefinitionTooltip.js +2 -2
  32. package/es/components/Tooltip/Tooltip.js +2 -2
  33. package/es/components/TreeView/TreeNode.js +2 -2
  34. package/es/components/TreeView/TreeView.js +1 -1
  35. package/es/components/UIShell/HeaderContainer.js +1 -1
  36. package/es/components/UIShell/HeaderMenu.js +2 -2
  37. package/es/components/UIShell/HeaderPanel.js +2 -2
  38. package/es/components/UIShell/SideNav.js +2 -2
  39. package/lib/components/Accordion/AccordionItem.d.ts +5 -0
  40. package/lib/components/Accordion/AccordionItem.js +0 -6
  41. package/lib/components/ComboBox/ComboBox.js +2 -2
  42. package/lib/components/ComposedModal/ComposedModal.js +2 -2
  43. package/lib/components/ContentSwitcher/ContentSwitcher.js +2 -2
  44. package/lib/components/DatePicker/DatePicker.js +2 -2
  45. package/lib/components/FileUploader/FileUploader.js +1 -1
  46. package/lib/components/FileUploader/FileUploaderButton.js +2 -2
  47. package/lib/components/FileUploader/FileUploaderDropContainer.js +2 -2
  48. package/lib/components/FileUploader/FileUploaderItem.js +2 -2
  49. package/lib/components/Loading/Loading.js +81 -1
  50. package/lib/components/Menu/Menu.js +2 -2
  51. package/lib/components/Menu/MenuItem.js +2 -2
  52. package/lib/components/Modal/Modal.js +3 -3
  53. package/lib/components/MultiSelect/FilterableMultiSelect.js +2 -2
  54. package/lib/components/MultiSelect/MultiSelect.js +2 -2
  55. package/lib/components/Notification/Notification.js +2 -2
  56. package/lib/components/NumberInput/NumberInput.js +2 -2
  57. package/lib/components/OverflowMenu/OverflowMenu.js +2 -2
  58. package/lib/components/OverflowMenuItem/OverflowMenuItem.js +1 -1
  59. package/lib/components/Pagination/Pagination.d.ts +1 -1
  60. package/lib/components/Pagination/Pagination.js +52 -53
  61. package/lib/components/Popover/index.js +1 -1
  62. package/lib/components/RadioTile/RadioTile.js +2 -2
  63. package/lib/components/Search/Search.js +2 -2
  64. package/lib/components/Slider/Slider.js +2 -2
  65. package/lib/components/Tabs/Tabs.js +2 -2
  66. package/lib/components/Tile/Tile.js +2 -2
  67. package/lib/components/Toggletip/index.js +2 -2
  68. package/lib/components/Tooltip/DefinitionTooltip.js +2 -2
  69. package/lib/components/Tooltip/Tooltip.js +2 -2
  70. package/lib/components/TreeView/TreeNode.js +2 -2
  71. package/lib/components/TreeView/TreeView.js +1 -1
  72. package/lib/components/UIShell/HeaderContainer.js +1 -1
  73. package/lib/components/UIShell/HeaderMenu.js +2 -2
  74. package/lib/components/UIShell/HeaderPanel.js +2 -2
  75. package/lib/components/UIShell/SideNav.js +2 -2
  76. package/package.json +11 -11
@@ -61,6 +61,11 @@ export interface AccordionToggleProps {
61
61
  className?: string;
62
62
  disabled?: boolean;
63
63
  onClick?: MouseEventHandler<HTMLButtonElement>;
64
+ /**
65
+ * @deprecated `AccordionItem` no longer passes an `onKeyDown` handler to
66
+ * the toggle. This prop is kept only so custom `renderToggle`
67
+ * implementations that reference it don't hit a breaking type change.
68
+ */
64
69
  onKeyDown?: (event: KeyboardEvent<HTMLButtonElement>) => void;
65
70
  type?: 'button';
66
71
  }
@@ -8,8 +8,6 @@
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
9
  import { AccordionContext } from "./AccordionProvider.js";
10
10
  import { Text } from "../Text/Text.js";
11
- import { Escape } from "../../internal/keyboard/keys.js";
12
- import { match } from "../../internal/keyboard/match.js";
13
11
  import { useId } from "../../internal/useId.js";
14
12
  import { deprecate } from "../../prop-types/deprecate.js";
15
13
  import React, { useContext, useEffect, useRef, useState } from "react";
@@ -60,9 +58,6 @@ function AccordionItem({ children, className: customClassName = "", open = false
60
58
  event
61
59
  });
62
60
  }
63
- function onKeyDown(event) {
64
- if (isOpen && match(event, Escape)) setIsOpen(false);
65
- }
66
61
  function onAnimationEnd(event) {
67
62
  if (handleAnimationEnd) handleAnimationEnd(event);
68
63
  }
@@ -76,7 +71,6 @@ function AccordionItem({ children, className: customClassName = "", open = false
76
71
  "aria-label": ariaLabel,
77
72
  className: `${prefix}--accordion__heading`,
78
73
  onClick,
79
- onKeyDown,
80
74
  type: "button",
81
75
  children: [/* @__PURE__ */ jsx(ChevronRight, { className: `${prefix}--accordion__arrow` }), /* @__PURE__ */ jsx(Text, {
82
76
  as: "div",
@@ -7,13 +7,13 @@
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
9
  import { Text } from "../Text/Text.js";
10
- import { End, Enter, Escape, Home, Space } from "../../internal/keyboard/keys.js";
11
- import { match } from "../../internal/keyboard/match.js";
12
10
  import { useId } from "../../internal/useId.js";
13
11
  import { deprecate } from "../../prop-types/deprecate.js";
14
12
  import { defaultItemToString } from "../../internal/defaultItemToString.js";
15
13
  import { isItemDisabled } from "../../internal/isItemDisabled.js";
16
14
  import { isComponentElement } from "../../internal/utils.js";
15
+ import { End, Enter, Escape, Home, Space } from "../../internal/keyboard/keys.js";
16
+ import { match } from "../../internal/keyboard/match.js";
17
17
  import { useFeatureFlag } from "../FeatureFlags/index.js";
18
18
  import { AILabel } from "../AILabel/index.js";
19
19
  import { mergeRefs } from "../../tools/mergeRefs.js";
@@ -7,11 +7,11 @@
7
7
 
8
8
  import { warning } from "../../internal/warning.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
- import { Escape, Tab } from "../../internal/keyboard/keys.js";
11
- import { match } from "../../internal/keyboard/match.js";
12
10
  import { useId } from "../../internal/useId.js";
13
11
  import { deprecate } from "../../prop-types/deprecate.js";
14
12
  import { isComponentElement } from "../../internal/utils.js";
13
+ import { Escape, Tab } from "../../internal/keyboard/keys.js";
14
+ import { match } from "../../internal/keyboard/match.js";
15
15
  import { useFeatureFlag } from "../FeatureFlags/index.js";
16
16
  import { AILabel } from "../AILabel/index.js";
17
17
  import { mergeRefs } from "../../tools/mergeRefs.js";
@@ -6,11 +6,11 @@
6
6
  */
7
7
 
8
8
  import { PrefixContext } from "../../internal/usePrefix.js";
9
+ import { deprecate } from "../../prop-types/deprecate.js";
10
+ import { isComponentElement } from "../../internal/utils.js";
9
11
  import { ArrowLeft, ArrowRight, Enter, Space } from "../../internal/keyboard/keys.js";
10
12
  import { match } from "../../internal/keyboard/match.js";
11
13
  import { getNextIndex } from "../../internal/keyboard/navigation.js";
12
- import { deprecate } from "../../prop-types/deprecate.js";
13
- import { isComponentElement } from "../../internal/utils.js";
14
14
  import { LayoutConstraint } from "../Layout/index.js";
15
15
  import Switch from "../Switch/Switch.js";
16
16
  import IconSwitch from "../Switch/IconSwitch.js";
@@ -6,10 +6,10 @@
6
6
  */
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
- import { Enter, Escape, Tab } from "../../internal/keyboard/keys.js";
10
- import { match } from "../../internal/keyboard/match.js";
11
9
  import { deprecate } from "../../prop-types/deprecate.js";
12
10
  import { isComponentElement } from "../../internal/utils.js";
11
+ import { Enter, Escape, Tab } from "../../internal/keyboard/keys.js";
12
+ import { match } from "../../internal/keyboard/match.js";
13
13
  import DatePickerInput_default from "../DatePickerInput/index.js";
14
14
  import { appendToPlugin } from "./plugins/appendToPlugin.js";
15
15
  import { fixEventsPlugin } from "./plugins/fixEventsPlugin.js";
@@ -7,9 +7,9 @@
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
9
  import { Text } from "../Text/Text.js";
10
+ import { useId } from "../../internal/useId.js";
10
11
  import { Enter, Space } from "../../internal/keyboard/keys.js";
11
12
  import { matches } from "../../internal/keyboard/match.js";
12
- import { useId } from "../../internal/useId.js";
13
13
  import { useFeatureFlag } from "../FeatureFlags/index.js";
14
14
  import { ButtonKinds } from "../Button/Button.js";
15
15
  import Filename from "./Filename.js";
@@ -7,10 +7,10 @@
7
7
 
8
8
  import { noopFn } from "../../internal/noopFn.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
- import { Enter, Space } from "../../internal/keyboard/keys.js";
11
- import { matches } from "../../internal/keyboard/match.js";
12
10
  import { useId } from "../../internal/useId.js";
13
11
  import { deprecate } from "../../prop-types/deprecate.js";
12
+ import { Enter, Space } from "../../internal/keyboard/keys.js";
13
+ import { matches } from "../../internal/keyboard/match.js";
14
14
  import { ButtonKinds } from "../Button/Button.js";
15
15
  import { useEffect, useRef, useState } from "react";
16
16
  import cx from "classnames";
@@ -7,10 +7,10 @@
7
7
 
8
8
  import { noopFn } from "../../internal/noopFn.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
- import { Enter, Space } from "../../internal/keyboard/keys.js";
11
- import { matches } from "../../internal/keyboard/match.js";
12
10
  import { useId } from "../../internal/useId.js";
13
11
  import { deprecate } from "../../prop-types/deprecate.js";
12
+ import { Enter, Space } from "../../internal/keyboard/keys.js";
13
+ import { matches } from "../../internal/keyboard/match.js";
14
14
  import { composeEventHandlers } from "../../tools/events.js";
15
15
  import { useRef, useState } from "react";
16
16
  import cx from "classnames";
@@ -8,10 +8,10 @@
8
8
  import { noopFn } from "../../internal/noopFn.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
10
  import { Text } from "../Text/Text.js";
11
- import { Enter, Space } from "../../internal/keyboard/keys.js";
12
- import { matches } from "../../internal/keyboard/match.js";
13
11
  import useIsomorphicEffect from "../../internal/useIsomorphicEffect.js";
14
12
  import { useId } from "../../internal/useId.js";
13
+ import { Enter, Space } from "../../internal/keyboard/keys.js";
14
+ import { matches } from "../../internal/keyboard/match.js";
15
15
  import { Tooltip } from "../Tooltip/Tooltip.js";
16
16
  import Filename from "./Filename.js";
17
17
  import { useRef, useState } from "react";
@@ -7,7 +7,9 @@
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
9
  import { deprecate } from "../../prop-types/deprecate.js";
10
- import "react";
10
+ import { Tab } from "../../internal/keyboard/keys.js";
11
+ import { match } from "../../internal/keyboard/match.js";
12
+ import { useEffect, useRef } from "react";
11
13
  import cx from "classnames";
12
14
  import PropTypes from "prop-types";
13
15
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -18,8 +20,78 @@ import { jsx, jsxs } from "react/jsx-runtime";
18
20
  * This source code is licensed under the Apache-2.0 license found in the
19
21
  * LICENSE file in the root directory of this source tree.
20
22
  */
23
+ const isModalDialog = (element) => {
24
+ if (element.matches("[aria-modal=\"true\"]")) return true;
25
+ if (!(element instanceof HTMLDialogElement) || !element.open) return false;
26
+ try {
27
+ return element.matches(":modal");
28
+ } catch {
29
+ return true;
30
+ }
31
+ };
32
+ const isLayeredOnTop = (target, overlay) => {
33
+ if (!(target instanceof Element)) return false;
34
+ for (let element = target; element; element = element.parentElement) if (isModalDialog(element)) return !element.contains(overlay);
35
+ return false;
36
+ };
37
+ const focusWithBorrowedTabIndex = (element) => {
38
+ const hadTabIndex = element.hasAttribute("tabindex");
39
+ if (!hadTabIndex) element.setAttribute("tabindex", "-1");
40
+ element.focus();
41
+ if (hadTabIndex) return;
42
+ if (document.activeElement === element) element.addEventListener("blur", () => element.removeAttribute("tabindex"), { once: true });
43
+ else element.removeAttribute("tabindex");
44
+ };
45
+ const restoreFocus = (overlay, previouslyFocused) => {
46
+ const activeElement = document.activeElement;
47
+ if (!(!activeElement || activeElement === document.body || overlay.contains(activeElement)) || !previouslyFocused?.isConnected) return;
48
+ previouslyFocused.focus();
49
+ if (document.activeElement === previouslyFocused) return;
50
+ const fallback = previouslyFocused.parentElement;
51
+ if (!fallback || fallback === document.body || fallback === document.documentElement) return;
52
+ focusWithBorrowedTabIndex(fallback);
53
+ };
54
+ const useFocusTrap = (overlayRef, active) => {
55
+ useEffect(() => {
56
+ const overlay = overlayRef.current;
57
+ if (!active || !overlay) return;
58
+ const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
59
+ if (!isLayeredOnTop(previouslyFocused, overlay)) overlay.focus();
60
+ let reclaiming = false;
61
+ const reclaimFocus = () => {
62
+ if (reclaiming) return;
63
+ reclaiming = true;
64
+ try {
65
+ overlay.focus();
66
+ } finally {
67
+ reclaiming = false;
68
+ }
69
+ };
70
+ const handleFocusIn = (event) => {
71
+ const { target } = event;
72
+ if (!(target instanceof Node) || overlay.contains(target)) return;
73
+ if (isLayeredOnTop(target, overlay)) return;
74
+ reclaimFocus();
75
+ };
76
+ const handleKeyDown = (event) => {
77
+ if (!match(event, Tab)) return;
78
+ if (isLayeredOnTop(event.target, overlay)) return;
79
+ event.preventDefault();
80
+ reclaimFocus();
81
+ };
82
+ document.addEventListener("focusin", handleFocusIn, true);
83
+ document.addEventListener("keydown", handleKeyDown, true);
84
+ return () => {
85
+ document.removeEventListener("focusin", handleFocusIn, true);
86
+ document.removeEventListener("keydown", handleKeyDown, true);
87
+ restoreFocus(overlay, previouslyFocused);
88
+ };
89
+ }, [overlayRef, active]);
90
+ };
21
91
  function Loading({ active = true, className: customClassName, withOverlay = true, small = false, description = "loading", ...rest }) {
22
92
  const prefix = usePrefix();
93
+ const overlayRef = useRef(null);
94
+ useFocusTrap(overlayRef, withOverlay && active);
23
95
  const loadingClassName = cx(customClassName, {
24
96
  [`${prefix}--loading`]: true,
25
97
  [`${prefix}--loading--small`]: small,
@@ -58,7 +130,15 @@ function Loading({ active = true, className: customClassName, withOverlay = true
58
130
  });
59
131
  return withOverlay ? /* @__PURE__ */ jsx("div", {
60
132
  className: overlayClassName,
61
- children: loading
133
+ role: "presentation",
134
+ children: /* @__PURE__ */ jsx("div", {
135
+ ref: overlayRef,
136
+ role: active ? "dialog" : void 0,
137
+ "aria-modal": active ? "true" : void 0,
138
+ "aria-label": active ? description : void 0,
139
+ tabIndex: active ? -1 : void 0,
140
+ children: loading
141
+ })
62
142
  }) : loading;
63
143
  }
64
144
  Loading.propTypes = {
@@ -6,10 +6,10 @@
6
6
  */
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
- import { ArrowDown, ArrowLeft, ArrowUp, Escape, Tab } from "../../internal/keyboard/keys.js";
10
- import { match } from "../../internal/keyboard/match.js";
11
9
  import { deprecate } from "../../prop-types/deprecate.js";
12
10
  import { useMergedRefs } from "../../internal/useMergedRefs.js";
11
+ import { ArrowDown, ArrowLeft, ArrowUp, Escape, Tab } from "../../internal/keyboard/keys.js";
12
+ import { match } from "../../internal/keyboard/match.js";
13
13
  import { MenuContext, menuReducer } from "./MenuContext.js";
14
14
  import { useLayoutDirection } from "../LayoutDirection/useLayoutDirection.js";
15
15
  import { canUseDOM } from "../../internal/environment.js";
@@ -7,11 +7,11 @@
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
9
  import { Text } from "../Text/Text.js";
10
- import { ArrowRight as ArrowRight$1, Enter, Space } from "../../internal/keyboard/keys.js";
11
- import { match } from "../../internal/keyboard/match.js";
12
10
  import { useId } from "../../internal/useId.js";
13
11
  import { defaultItemToString } from "../../internal/defaultItemToString.js";
14
12
  import { useMergedRefs } from "../../internal/useMergedRefs.js";
13
+ import { ArrowRight as ArrowRight$1, Enter, Space } from "../../internal/keyboard/keys.js";
14
+ import { match } from "../../internal/keyboard/match.js";
15
15
  import { MenuContext } from "./MenuContext.js";
16
16
  import { useLayoutDirection } from "../LayoutDirection/useLayoutDirection.js";
17
17
  import { Menu as Menu$1 } from "./Menu.js";
@@ -9,13 +9,13 @@ import { noopFn } from "../../internal/noopFn.js";
9
9
  import { warning } from "../../internal/warning.js";
10
10
  import { usePrefix } from "../../internal/usePrefix.js";
11
11
  import { Text } from "../Text/Text.js";
12
- import { Enter, Escape, Tab } from "../../internal/keyboard/keys.js";
13
- import { match } from "../../internal/keyboard/match.js";
14
- import { selectorTabbable } from "../../internal/keyboard/navigation.js";
15
12
  import { useId } from "../../internal/useId.js";
16
13
  import { deprecate } from "../../prop-types/deprecate.js";
17
14
  import { isComponentElement } from "../../internal/utils.js";
18
15
  import { useMergedRefs } from "../../internal/useMergedRefs.js";
16
+ import { Enter, Escape, Tab } from "../../internal/keyboard/keys.js";
17
+ import { match } from "../../internal/keyboard/match.js";
18
+ import { selectorTabbable } from "../../internal/keyboard/navigation.js";
19
19
  import { useFeatureFlag } from "../FeatureFlags/index.js";
20
20
  import { IconButton } from "../IconButton/index.js";
21
21
  import Button_default from "../Button/index.js";
@@ -6,14 +6,14 @@
6
6
  */
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
- import { Delete, End, Enter, Escape, Home, Space, Tab } from "../../internal/keyboard/keys.js";
10
- import { match } from "../../internal/keyboard/match.js";
11
9
  import useIsomorphicEffect from "../../internal/useIsomorphicEffect.js";
12
10
  import { useId } from "../../internal/useId.js";
13
11
  import { deprecate } from "../../prop-types/deprecate.js";
14
12
  import { defaultItemToString } from "../../internal/defaultItemToString.js";
15
13
  import { isItemDisabled } from "../../internal/isItemDisabled.js";
16
14
  import { isComponentElement } from "../../internal/utils.js";
15
+ import { Delete, End, Enter, Escape, Home, Space, Tab } from "../../internal/keyboard/keys.js";
16
+ import { match } from "../../internal/keyboard/match.js";
17
17
  import { AILabel } from "../AILabel/index.js";
18
18
  import { mergeRefs } from "../../tools/mergeRefs.js";
19
19
  import { hasHelperText } from "../../internal/hasHelperText.js";
@@ -7,14 +7,14 @@
7
7
 
8
8
  import { noopFn } from "../../internal/noopFn.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
- import { ArrowDown, Delete, Enter, Escape, Space, Tab } from "../../internal/keyboard/keys.js";
11
- import { match } from "../../internal/keyboard/match.js";
12
10
  import useIsomorphicEffect from "../../internal/useIsomorphicEffect.js";
13
11
  import { useId } from "../../internal/useId.js";
14
12
  import { deprecate } from "../../prop-types/deprecate.js";
15
13
  import { defaultItemToString } from "../../internal/defaultItemToString.js";
16
14
  import { isItemDisabled } from "../../internal/isItemDisabled.js";
17
15
  import { isComponentElement } from "../../internal/utils.js";
16
+ import { ArrowDown, Delete, Enter, Escape, Space, Tab } from "../../internal/keyboard/keys.js";
17
+ import { match } from "../../internal/keyboard/match.js";
18
18
  import { useFeatureFlag } from "../FeatureFlags/index.js";
19
19
  import { AILabel } from "../AILabel/index.js";
20
20
  import { mergeRefs } from "../../tools/mergeRefs.js";
@@ -9,12 +9,12 @@ import { noopFn } from "../../internal/noopFn.js";
9
9
  import { warning } from "../../internal/warning.js";
10
10
  import { usePrefix } from "../../internal/usePrefix.js";
11
11
  import { Text } from "../Text/Text.js";
12
- import { Escape, Tab } from "../../internal/keyboard/keys.js";
13
- import { match, matches } from "../../internal/keyboard/match.js";
14
12
  import useIsomorphicEffect from "../../internal/useIsomorphicEffect.js";
15
13
  import { useId } from "../../internal/useId.js";
16
14
  import { deprecate } from "../../prop-types/deprecate.js";
17
15
  import { deprecateValuesWithin } from "../../prop-types/deprecateValuesWithin.js";
16
+ import { Escape, Tab } from "../../internal/keyboard/keys.js";
17
+ import { match, matches } from "../../internal/keyboard/match.js";
18
18
  import { useFeatureFlag } from "../FeatureFlags/index.js";
19
19
  import { useInteractiveChildrenNeedDescription, useNoInteractiveChildren } from "../../internal/useNoInteractiveChildren.js";
20
20
  import Button_default from "../Button/index.js";
@@ -7,11 +7,11 @@
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
9
  import { Text } from "../Text/Text.js";
10
- import { ArrowDown, ArrowUp as ArrowUp$1 } from "../../internal/keyboard/keys.js";
11
- import { match } from "../../internal/keyboard/match.js";
12
10
  import { deprecate } from "../../prop-types/deprecate.js";
13
11
  import { isComponentElement } from "../../internal/utils.js";
14
12
  import { useMergedRefs } from "../../internal/useMergedRefs.js";
13
+ import { ArrowDown, ArrowUp as ArrowUp$1 } from "../../internal/keyboard/keys.js";
14
+ import { match } from "../../internal/keyboard/match.js";
15
15
  import { AILabel } from "../AILabel/index.js";
16
16
  import { useControllableState } from "../../internal/useControllableState.js";
17
17
  import { useNormalizedInputProps } from "../../internal/useNormalizedInputProps.js";
@@ -7,11 +7,11 @@
7
7
 
8
8
  import { noopFn } from "../../internal/noopFn.js";
9
9
  import { PrefixContext } from "../../internal/usePrefix.js";
10
- import { ArrowDown, ArrowLeft, ArrowRight as ArrowRight$1, ArrowUp as ArrowUp$1, Escape, Tab } from "../../internal/keyboard/keys.js";
11
- import { matches } from "../../internal/keyboard/match.js";
12
10
  import { setupGetInstanceId } from "../../tools/setupGetInstanceId.js";
13
11
  import { deprecate } from "../../prop-types/deprecate.js";
14
12
  import { deprecateValuesWithin } from "../../prop-types/deprecateValuesWithin.js";
13
+ import { ArrowDown, ArrowLeft, ArrowRight as ArrowRight$1, ArrowUp as ArrowUp$1, Escape, Tab } from "../../internal/keyboard/keys.js";
14
+ import { matches } from "../../internal/keyboard/match.js";
15
15
  import { mapPopoverAlign } from "../../tools/mapPopoverAlign.js";
16
16
  import { IconButton } from "../IconButton/index.js";
17
17
  import { mergeRefs } from "../../tools/mergeRefs.js";
@@ -8,9 +8,9 @@
8
8
  import { warning } from "../../internal/warning.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
10
  import { Text } from "../Text/Text.js";
11
+ import { useId } from "../../internal/useId.js";
11
12
  import { ArrowDown, ArrowUp } from "../../internal/keyboard/keys.js";
12
13
  import { match } from "../../internal/keyboard/match.js";
13
- import { useId } from "../../internal/useId.js";
14
14
  import { forwardRef } from "react";
15
15
  import cx from "classnames";
16
16
  import PropTypes from "prop-types";
@@ -108,7 +108,7 @@ export interface PaginationProps extends Omit<React.HTMLAttributes<HTMLDivElemen
108
108
  /**
109
109
  * The choices for `pageSize`.
110
110
  */
111
- pageSizes: number[] | PaginationPageSize[];
111
+ pageSizes?: Array<number | PaginationPageSize>;
112
112
  /**
113
113
  * The translatable text showing the current page.
114
114
  */
@@ -25,14 +25,11 @@ import isEqual from "react-fast-compare";
25
25
  * This source code is licensed under the Apache-2.0 license found in the
26
26
  * LICENSE file in the root directory of this source tree.
27
27
  */
28
- const isPaginationPageSizeArray = (sizes) => typeof sizes[0] === "object" && sizes[0] !== null;
29
- const mapPageSizesToObject = (sizes) => {
30
- if (isPaginationPageSizeArray(sizes)) return sizes;
31
- return sizes.map((size) => ({
32
- text: String(size),
33
- value: size
34
- }));
35
- };
28
+ const mapPageSizesToObject = (sizes) => sizes && sizes.length ? sizes.map((size) => typeof size === "object" ? size : {
29
+ text: String(size),
30
+ value: size
31
+ }) : void 0;
32
+ const DEFAULT_PAGE_SIZE = 10;
36
33
  function renderSelectItems(total) {
37
34
  let counter = 1;
38
35
  const itemArr = [];
@@ -46,12 +43,11 @@ function renderSelectItems(total) {
46
43
  return itemArr;
47
44
  }
48
45
  const getPageSize = (pageSizes, pageSize) => {
49
- if (typeof pageSize !== "undefined") {
50
- if (pageSizes.find((size) => {
51
- return pageSize === size.value;
52
- })) return pageSize;
46
+ if (!pageSizes) {
47
+ const resolved = pageSize ?? DEFAULT_PAGE_SIZE;
48
+ return resolved > 0 ? resolved : DEFAULT_PAGE_SIZE;
53
49
  }
54
- return pageSizes[0].value;
50
+ return typeof pageSize !== "undefined" && pageSizes.some((size) => pageSize === size.value) ? pageSize : pageSizes[0].value;
55
51
  };
56
52
  const Pagination = React.forwardRef(({ backwardText = "Previous page", backwardTextTooltipPosition = "top", className: customClassName = "", disabled = false, forwardText = "Next page", forwardTextTooltipPosition = "top", id, isLastPage = false, itemText = (min, max) => `${min}–${max} items`, itemRangeText = (min, max, total) => `${min}–${max} of ${total} items`, itemsPerPageText = "Items per page:", onChange, pageNumberText: _pageNumberText, pageRangeText = (_current, total) => `of ${total} ${total === 1 ? "page" : "pages"}`, pageSelectLabelText = (total) => `Page of ${total} ${total === 1 ? "page" : "pages"}`, page: controlledPage = 1, pageInputDisabled, renderPageSelect, pageSize: controlledPageSize, pageSizeInputDisabled, pageSizes: controlledPageSizes, pageText = (page) => `page ${page}`, pagesUnknown = false, size = "md", totalItems, ...rest }, ref) => {
57
53
  const prefix = usePrefix();
@@ -88,6 +84,13 @@ const Pagination = React.forwardRef(({ backwardText = "Previous page", backwardT
88
84
  [`${prefix}--pagination__button--no-index`]: forwardButtonDisabled
89
85
  });
90
86
  const selectItems = renderPageSelect ? [] : renderSelectItems(totalPages);
87
+ const pageSelectNode = pagesUnknown ? null : renderPageSelect?.({
88
+ currentPage: page,
89
+ totalPages,
90
+ currentPageSize: pageSize,
91
+ pageSelectLabelText: pageSelectLabelText(totalPages),
92
+ onSetPage: handleSetPage
93
+ }) ?? null;
91
94
  const focusMap = {
92
95
  backward: backBtnRef,
93
96
  forward: forwardBtnRef
@@ -116,7 +119,13 @@ const Pagination = React.forwardRef(({ backwardText = "Previous page", backwardT
116
119
  setPage(controlledPage);
117
120
  }, [controlledPage]);
118
121
  useEffect(() => {
119
- if (typeof prevControlledPageSizes === "undefined" || isEqual(prevControlledPageSizes, normalizedControlledPageSizes)) return;
122
+ if (isEqual(prevControlledPageSizes, normalizedControlledPageSizes)) return;
123
+ if (!normalizedControlledPageSizes) {
124
+ const nextPageSize = getPageSize(void 0, controlledPageSize);
125
+ setPageSizes(void 0);
126
+ setPageSize(nextPageSize);
127
+ return;
128
+ }
120
129
  setPageSizes((prev) => isEqual(normalizedControlledPageSizes, prev) ? prev : normalizedControlledPageSizes);
121
130
  const nextPageSize = getPageSize(normalizedControlledPageSizes, controlledPageSize ?? pageSize);
122
131
  const hasPageSize = normalizedControlledPageSizes.some((size) => {
@@ -204,46 +213,36 @@ const Pagination = React.forwardRef(({ backwardText = "Previous page", backwardT
204
213
  ref,
205
214
  ...rest,
206
215
  children: [/* @__PURE__ */ jsxs("div", {
207
- className: `${prefix}--pagination__left`,
208
- children: [
209
- /* @__PURE__ */ jsx("label", {
210
- id: `${prefix}-pagination-select-${inputId}-count-label`,
211
- className: `${prefix}--pagination__text`,
212
- htmlFor: `${prefix}-pagination-select-${inputId}`,
213
- children: itemsPerPageText
214
- }),
215
- /* @__PURE__ */ jsx(Select_default, {
216
- id: `${prefix}-pagination-select-${inputId}`,
217
- className: `${prefix}--select__item-count`,
218
- labelText: "",
219
- hideLabel: true,
220
- noLabel: true,
221
- inline: true,
222
- onChange: handleSizeChange,
223
- disabled: pageSizeInputDisabled || disabled,
224
- value: pageSize,
225
- children: pageSizes.map((sizeObj) => /* @__PURE__ */ jsx(SelectItem_default, {
226
- value: sizeObj.value,
227
- text: String(sizeObj.text)
228
- }, sizeObj.value))
229
- }),
230
- /* @__PURE__ */ jsx("span", {
231
- className: `${prefix}--pagination__text ${prefix}--pagination__items-count`,
232
- children: pagesUnknown || !totalItems ? totalItems === 0 ? itemRangeText(0, 0, 0) : itemText(pageSize * (page - 1) + 1, page * pageSize) : itemRangeText(Math.min(pageSize * (page - 1) + 1, totalItems), Math.min(page * pageSize, totalItems), totalItems)
233
- })
234
- ]
216
+ className: cx(`${prefix}--pagination__left`, { [`${prefix}--pagination__left--no-sizer`]: !pageSizes }),
217
+ children: [pageSizes && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("label", {
218
+ id: `${prefix}-pagination-select-${inputId}-count-label`,
219
+ className: `${prefix}--pagination__text`,
220
+ htmlFor: `${prefix}-pagination-select-${inputId}`,
221
+ children: itemsPerPageText
222
+ }), /* @__PURE__ */ jsx(Select_default, {
223
+ id: `${prefix}-pagination-select-${inputId}`,
224
+ className: `${prefix}--select__item-count`,
225
+ labelText: "",
226
+ hideLabel: true,
227
+ noLabel: true,
228
+ inline: true,
229
+ onChange: handleSizeChange,
230
+ disabled: pageSizeInputDisabled || disabled,
231
+ value: pageSize,
232
+ children: pageSizes.map((sizeObj) => /* @__PURE__ */ jsx(SelectItem_default, {
233
+ value: sizeObj.value,
234
+ text: String(sizeObj.text)
235
+ }, sizeObj.value))
236
+ })] }), /* @__PURE__ */ jsx("span", {
237
+ className: `${prefix}--pagination__text ${prefix}--pagination__items-count`,
238
+ children: pagesUnknown || !totalItems ? totalItems === 0 ? itemRangeText(0, 0, 0) : itemText(pageSize * (page - 1) + 1, page * pageSize) : itemRangeText(Math.min(pageSize * (page - 1) + 1, totalItems), Math.min(page * pageSize, totalItems), totalItems)
239
+ })]
235
240
  }), /* @__PURE__ */ jsxs("div", {
236
- className: `${prefix}--pagination__right`,
241
+ className: cx(`${prefix}--pagination__right`, { [`${prefix}--pagination__right--no-content`]: !pagesUnknown && !!renderPageSelect }),
237
242
  children: [pagesUnknown ? /* @__PURE__ */ jsx("span", {
238
243
  className: `${prefix}--pagination__text ${prefix}--pagination__page-text ${prefix}--pagination__unknown-pages-text`,
239
244
  children: pageText(page)
240
- }) : /* @__PURE__ */ jsxs(Fragment, { children: [renderPageSelect ? renderPageSelect({
241
- currentPage: page,
242
- totalPages,
243
- currentPageSize: pageSize,
244
- pageSelectLabelText: pageSelectLabelText(totalPages),
245
- onSetPage: handleSetPage
246
- }) : /* @__PURE__ */ jsx(Select_default, {
245
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [renderPageSelect ? pageSelectNode : /* @__PURE__ */ jsx(Select_default, {
247
246
  id: `${prefix}-pagination-select-${inputId}-right`,
248
247
  className: `${prefix}--select__page-number`,
249
248
  labelText: pageSelectLabelText(totalPages),
@@ -255,7 +254,7 @@ const Pagination = React.forwardRef(({ backwardText = "Previous page", backwardT
255
254
  children: selectItems
256
255
  }, page), /* @__PURE__ */ jsx("span", {
257
256
  className: `${prefix}--pagination__text`,
258
- children: pageRangeText(page, totalPages)
257
+ children: pageSelectNode == null && renderPageSelect ? `${page} ${pageRangeText(page, totalPages)}` : pageRangeText(page, totalPages)
259
258
  })] }), /* @__PURE__ */ jsxs("div", {
260
259
  className: `${prefix}--pagination__control-buttons`,
261
260
  children: [/* @__PURE__ */ jsx(IconButton, {
@@ -376,10 +375,10 @@ Pagination.propTypes = {
376
375
  /**
377
376
  * The choices for `pageSize`.
378
377
  */
379
- pageSizes: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number.isRequired), PropTypes.arrayOf(PropTypes.shape({
378
+ pageSizes: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.shape({
380
379
  text: PropTypes.string.isRequired,
381
380
  value: PropTypes.number.isRequired
382
- }).isRequired)]).isRequired,
381
+ })])),
383
382
  /**
384
383
  * The translatable text showing the current page.
385
384
  */
@@ -6,12 +6,12 @@
6
6
  */
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
- import { selectorTabbable } from "../../internal/keyboard/navigation.js";
10
9
  import useIsomorphicEffect from "../../internal/useIsomorphicEffect.js";
11
10
  import { deprecateValuesWithin } from "../../prop-types/deprecateValuesWithin.js";
12
11
  import { isComponentElement } from "../../internal/utils.js";
13
12
  import { useMergedRefs } from "../../internal/useMergedRefs.js";
14
13
  import { useEvent, useWindowEvent } from "../../internal/useEvent.js";
14
+ import { selectorTabbable } from "../../internal/keyboard/navigation.js";
15
15
  import { mapPopoverAlign } from "../../tools/mapPopoverAlign.js";
16
16
  import { useFeatureFlag } from "../FeatureFlags/index.js";
17
17
  import React, { forwardRef, useEffect, useMemo, useRef } from "react";
@@ -8,11 +8,11 @@
8
8
  import { noopFn } from "../../internal/noopFn.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
10
  import { Text } from "../Text/Text.js";
11
- import { Enter, Space } from "../../internal/keyboard/keys.js";
12
- import { matches } from "../../internal/keyboard/match.js";
13
11
  import { useFallbackId } from "../../internal/useId.js";
14
12
  import { deprecate } from "../../prop-types/deprecate.js";
15
13
  import { isComponentElement } from "../../internal/utils.js";
14
+ import { Enter, Space } from "../../internal/keyboard/keys.js";
15
+ import { matches } from "../../internal/keyboard/match.js";
16
16
  import { useFeatureFlag } from "../FeatureFlags/index.js";
17
17
  import { AILabel } from "../AILabel/index.js";
18
18
  import React, { cloneElement } from "react";
@@ -7,11 +7,11 @@
7
7
 
8
8
  import { noopFn } from "../../internal/noopFn.js";
9
9
  import { usePrefix } from "../../internal/usePrefix.js";
10
- import { Enter, Escape, Space } from "../../internal/keyboard/keys.js";
11
- import { match } from "../../internal/keyboard/match.js";
12
10
  import { useId } from "../../internal/useId.js";
13
11
  import { deprecate } from "../../prop-types/deprecate.js";
14
12
  import { useMergedRefs } from "../../internal/useMergedRefs.js";
13
+ import { Enter, Escape, Space } from "../../internal/keyboard/keys.js";
14
+ import { match } from "../../internal/keyboard/match.js";
15
15
  import { Tooltip } from "../Tooltip/Tooltip.js";
16
16
  import { composeEventHandlers } from "../../tools/events.js";
17
17
  import { FormContext } from "../FluidForm/FormContext.js";