@carbon/react 1.16.0 → 1.17.0-rc.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.
Files changed (71) hide show
  1. package/es/components/Checkbox/Checkbox.Skeleton.d.ts +18 -0
  2. package/es/components/Checkbox/Checkbox.Skeleton.js +1 -2
  3. package/es/components/Checkbox/Checkbox.d.ts +47 -0
  4. package/es/components/Checkbox/Checkbox.js +6 -7
  5. package/es/components/Checkbox/index.d.ts +10 -0
  6. package/es/components/Checkbox/index.js +10 -0
  7. package/es/components/ComposedModal/ComposedModal.js +4 -3
  8. package/es/components/DataTable/TableToolbarSearch.js +1 -1
  9. package/es/components/ExpandableSearch/ExpandableSearch.js +1 -1
  10. package/es/components/Grid/Grid.js +0 -5
  11. package/es/components/Modal/Modal.js +5 -4
  12. package/es/components/RadioButtonGroup/RadioButtonGroup.js +8 -2
  13. package/es/components/Search/Search.js +160 -184
  14. package/es/components/Search/index.js +2 -8
  15. package/es/components/Tab/index.js +1 -1
  16. package/es/components/Tabs/Tabs.Skeleton.js +6 -6
  17. package/es/components/Tabs/Tabs.js +582 -508
  18. package/es/components/Tabs/index.js +2 -12
  19. package/es/components/Tabs/{next/usePressable.js → usePressable.js} +1 -1
  20. package/es/components/Text/Text.d.ts +33 -0
  21. package/es/components/Text/Text.js +8 -5
  22. package/es/components/Text/TextDirection.d.ts +35 -0
  23. package/es/components/Text/TextDirectionContext.js +2 -0
  24. package/es/components/Text/createTextComponent.d.ts +18 -0
  25. package/es/components/Text/index.d.ts +18 -0
  26. package/es/components/Text/index.js +2 -0
  27. package/es/components/TextArea/TextArea.js +19 -2
  28. package/es/components/Tile/Tile.js +339 -502
  29. package/es/index.js +9 -9
  30. package/es/internal/usePrefix.d.ts +9 -0
  31. package/lib/components/Checkbox/Checkbox.Skeleton.d.ts +18 -0
  32. package/lib/components/Checkbox/Checkbox.Skeleton.js +1 -2
  33. package/lib/components/Checkbox/Checkbox.d.ts +47 -0
  34. package/lib/components/Checkbox/Checkbox.js +6 -7
  35. package/lib/components/Checkbox/index.d.ts +10 -0
  36. package/lib/components/Checkbox/index.js +18 -0
  37. package/lib/components/ComposedModal/ComposedModal.js +4 -3
  38. package/lib/components/DataTable/TableToolbarSearch.js +2 -2
  39. package/lib/components/ExpandableSearch/ExpandableSearch.js +3 -3
  40. package/lib/components/Grid/Grid.js +0 -5
  41. package/lib/components/Modal/Modal.js +5 -4
  42. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +8 -2
  43. package/lib/components/Search/Search.js +159 -183
  44. package/lib/components/Search/index.js +2 -25
  45. package/lib/components/Tab/index.js +1 -1
  46. package/lib/components/Tabs/Tabs.Skeleton.js +6 -6
  47. package/lib/components/Tabs/Tabs.js +586 -507
  48. package/lib/components/Tabs/index.js +7 -33
  49. package/lib/components/Tabs/{next/usePressable.js → usePressable.js} +1 -1
  50. package/lib/components/Text/Text.d.ts +33 -0
  51. package/lib/components/Text/Text.js +8 -5
  52. package/lib/components/Text/TextDirection.d.ts +35 -0
  53. package/lib/components/Text/TextDirectionContext.js +2 -0
  54. package/lib/components/Text/createTextComponent.d.ts +18 -0
  55. package/lib/components/Text/index.d.ts +18 -0
  56. package/lib/components/Text/index.js +4 -0
  57. package/lib/components/TextArea/TextArea.js +18 -1
  58. package/lib/components/Tile/Tile.js +336 -499
  59. package/lib/index.js +76 -76
  60. package/lib/internal/usePrefix.d.ts +9 -0
  61. package/package.json +8 -4
  62. package/es/components/Search/next/Search.js +0 -265
  63. package/es/components/Tabs/next/Tabs.Skeleton.js +0 -53
  64. package/es/components/Tabs/next/Tabs.js +0 -692
  65. package/es/components/Tile/index.js +0 -19
  66. package/es/components/Tile/next/Tile.js +0 -604
  67. package/lib/components/Search/next/Search.js +0 -275
  68. package/lib/components/Tabs/next/Tabs.Skeleton.js +0 -63
  69. package/lib/components/Tabs/next/Tabs.js +0 -708
  70. package/lib/components/Tile/index.js +0 -48
  71. package/lib/components/Tile/next/Tile.js +0 -619
@@ -5,614 +5,688 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import { inherits as _inherits, createSuper as _createSuper, classCallCheck as _classCallCheck, defineProperty as _defineProperty, assertThisInitialized as _assertThisInitialized, createClass as _createClass, objectWithoutProperties as _objectWithoutProperties, extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import PropTypes from 'prop-types';
10
- import React__default from 'react';
11
- import cx from 'classnames';
8
+ import { slicedToArray as _slicedToArray, objectWithoutProperties as _objectWithoutProperties, defineProperty as _defineProperty, extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
12
9
  import { ChevronLeft, ChevronRight } from '@carbon/icons-react';
10
+ import cx from 'classnames';
13
11
  import debounce from 'lodash.debounce';
14
- import TabContent from '../TabContent/TabContent.js';
15
- import { PrefixContext } from '../../internal/usePrefix.js';
16
- import { match, matches } from '../../internal/keyboard/match.js';
17
- import { ArrowLeft, ArrowRight, Enter, Space, Home, End } from '../../internal/keyboard/keys.js';
12
+ import PropTypes from 'prop-types';
13
+ import React__default, { useState, useRef, useCallback, useEffect } from 'react';
14
+ import { Tooltip } from '../Tooltip/next/Tooltip.js';
15
+ import { useControllableState } from '../../internal/useControllableState.js';
16
+ import { useEffectOnce } from '../../internal/useEffectOnce.js';
17
+ import { useId } from '../../internal/useId.js';
18
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
19
+ import { useMergedRefs } from '../../internal/useMergedRefs.js';
20
+ import { getInteractiveContent } from '../../internal/useNoInteractiveChildren.js';
21
+ import { usePrefix } from '../../internal/usePrefix.js';
22
+ import { usePressable } from './usePressable.js';
23
+ import { matches, match } from '../../internal/keyboard/match.js';
24
+ import { ArrowRight, ArrowLeft, Home, End } from '../../internal/keyboard/keys.js';
18
25
 
19
26
  var _ChevronLeft, _ChevronRight;
20
27
 
21
- var _excluded = ["className", "type", "light", "onSelectionChange", "scrollDebounceWait", "scrollIntoView", "selectionMode", "tabContentClassName", "leftOverflowButtonProps", "rightOverflowButtonProps"];
22
-
23
- var Tabs = /*#__PURE__*/function (_React$Component) {
24
- _inherits(Tabs, _React$Component);
25
-
26
- var _super = _createSuper(Tabs);
28
+ var _excluded = ["activation", "aria-label", "children", "className", "contained", "iconSize", "leftOverflowButtonProps", "light", "rightOverflowButtonProps", "scrollDebounceWait", "scrollIntoView"],
29
+ _excluded2 = ["as", "children", "className", "disabled", "onClick", "onKeyDown"],
30
+ _excluded3 = ["children", "className", "defaultOpen", "enterDelayMs", "leaveDelayMs", "label"],
31
+ _excluded4 = ["children", "className"];
27
32
 
28
- function Tabs() {
29
- var _this;
30
-
31
- _classCallCheck(this, Tabs);
32
-
33
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
34
- args[_key] = arguments[_key];
35
- }
36
-
37
- _this = _super.call.apply(_super, [this].concat(args));
38
-
39
- _defineProperty(_assertThisInitialized(_this), "state", {
40
- horizontalOverflow: false
41
- });
33
+ var TabsContext = /*#__PURE__*/React__default.createContext(); // Used to keep track of position in a tablist
42
34
 
43
- _defineProperty(_assertThisInitialized(_this), "tablist", /*#__PURE__*/React__default.createRef());
35
+ var TabContext = /*#__PURE__*/React__default.createContext(); // Used to keep track of position in a list of tab panels
44
36
 
45
- _defineProperty(_assertThisInitialized(_this), "leftOverflowNavButton", /*#__PURE__*/React__default.createRef());
37
+ var TabPanelContext = /*#__PURE__*/React__default.createContext();
46
38
 
47
- _defineProperty(_assertThisInitialized(_this), "rightOverflowNavButton", /*#__PURE__*/React__default.createRef());
39
+ function Tabs(_ref) {
40
+ var children = _ref.children,
41
+ _ref$defaultSelectedI = _ref.defaultSelectedIndex,
42
+ defaultSelectedIndex = _ref$defaultSelectedI === void 0 ? 0 : _ref$defaultSelectedI,
43
+ _onChange = _ref.onChange,
44
+ controlledSelectedIndex = _ref.selectedIndex;
45
+ var baseId = useId('ccs'); // The active index is used to track the element which has focus in our tablist
48
46
 
49
- _defineProperty(_assertThisInitialized(_this), "OVERFLOW_BUTTON_OFFSET", 40);
47
+ var _useState = useState(defaultSelectedIndex),
48
+ _useState2 = _slicedToArray(_useState, 2),
49
+ activeIndex = _useState2[0],
50
+ setActiveIndex = _useState2[1]; // The selected index is used for the tab/panel pairing which is "visible"
50
51
 
51
- _defineProperty(_assertThisInitialized(_this), "handleScroll", function () {
52
- var _this$tablist;
53
52
 
54
- if (!((_this$tablist = _this.tablist) !== null && _this$tablist !== void 0 && _this$tablist.current)) {
55
- return;
53
+ var _useControllableState = useControllableState({
54
+ value: controlledSelectedIndex,
55
+ defaultValue: defaultSelectedIndex,
56
+ onChange: function onChange(value) {
57
+ if (_onChange) {
58
+ _onChange({
59
+ selectedIndex: value
60
+ });
56
61
  }
62
+ }
63
+ }),
64
+ _useControllableState2 = _slicedToArray(_useControllableState, 2),
65
+ selectedIndex = _useControllableState2[0],
66
+ setSelectedIndex = _useControllableState2[1];
67
+
68
+ var value = {
69
+ baseId: baseId,
70
+ activeIndex: activeIndex,
71
+ defaultSelectedIndex: defaultSelectedIndex,
72
+ setActiveIndex: setActiveIndex,
73
+ selectedIndex: selectedIndex,
74
+ setSelectedIndex: setSelectedIndex
75
+ };
76
+ return /*#__PURE__*/React__default.createElement(TabsContext.Provider, {
77
+ value: value
78
+ }, children);
79
+ }
80
+
81
+ Tabs.propTypes = {
82
+ /**
83
+ * Provide child elements to be rendered inside of the `Tabs`.
84
+ * These elements should render either `TabsList` or `TabsPanels`
85
+ */
86
+ children: PropTypes.node,
57
87
 
58
- var _this$tablist$current = _this.tablist.current,
59
- tablistClientWidth = _this$tablist$current.clientWidth,
60
- tablistScrollLeft = _this$tablist$current.scrollLeft,
61
- tablistScrollWidth = _this$tablist$current.scrollWidth;
62
-
63
- _this.setState({
64
- tablistClientWidth: tablistClientWidth,
65
- horizontalOverflow: tablistScrollWidth > tablistClientWidth,
66
- tablistScrollWidth: tablistScrollWidth,
67
- tablistScrollLeft: tablistScrollLeft
68
- });
69
- });
70
-
71
- _defineProperty(_assertThisInitialized(_this), "_debouncedHandleWindowResize", null);
72
-
73
- _defineProperty(_assertThisInitialized(_this), "_handleWindowResize", _this.handleScroll);
74
-
75
- _defineProperty(_assertThisInitialized(_this), "_debouncedHandleScroll", null);
76
-
77
- _defineProperty(_assertThisInitialized(_this), "_handleScroll", _this.handleScroll);
78
-
79
- _defineProperty(_assertThisInitialized(_this), "getEnabledTabs", function () {
80
- return React__default.Children.toArray(_this.props.children).reduce(function (enabledTabs, tab, index) {
81
- return !tab.props.disabled ? enabledTabs.concat(index) : enabledTabs;
82
- }, []);
83
- });
88
+ /**
89
+ * Specify which content tab should be initially selected when the component
90
+ * is first rendered
91
+ */
92
+ defaultSelectedIndex: PropTypes.number,
84
93
 
85
- _defineProperty(_assertThisInitialized(_this), "getNextIndex", function (index, direction) {
86
- var enabledTabs = _this.getEnabledTabs();
94
+ /**
95
+ * Provide an optional function which is called whenever the state of the
96
+ * `Tabs` changes
97
+ */
98
+ onChange: PropTypes.func,
87
99
 
88
- var nextIndex = Math.max(enabledTabs.indexOf(index) + direction, // For `tab` not found in `enabledTabs`
89
- -1);
90
- var nextIndexLooped = nextIndex >= 0 && nextIndex < enabledTabs.length ? nextIndex : nextIndex - Math.sign(nextIndex) * enabledTabs.length;
91
- return enabledTabs[nextIndexLooped];
92
- });
100
+ /**
101
+ * Control which content panel is currently selected. This puts the component
102
+ * in a controlled mode and should be used along with `onChange`
103
+ */
104
+ selectedIndex: PropTypes.number
105
+ };
106
+ /**
107
+ * Get the next index for a given keyboard event given a count of the total
108
+ * items and the current index
109
+ * @param {Event} event
110
+ * @param {number} total
111
+ * @param {number} index
112
+ * @returns {number}
113
+ */
93
114
 
94
- _defineProperty(_assertThisInitialized(_this), "getDirection", function (evt) {
95
- if (match(evt, ArrowLeft)) {
96
- return -1;
97
- }
115
+ function getNextIndex(event, total, index) {
116
+ if (match(event, ArrowRight)) {
117
+ return (index + 1) % total;
118
+ } else if (match(event, ArrowLeft)) {
119
+ return (total + index - 1) % total;
120
+ } else if (match(event, Home)) {
121
+ return 0;
122
+ } else if (match(event, End)) {
123
+ return total - 1;
124
+ }
125
+ }
126
+
127
+ function TabList(_ref2) {
128
+ var _cx;
129
+
130
+ var _ref2$activation = _ref2.activation,
131
+ activation = _ref2$activation === void 0 ? 'automatic' : _ref2$activation,
132
+ label = _ref2['aria-label'],
133
+ children = _ref2.children,
134
+ customClassName = _ref2.className,
135
+ _ref2$contained = _ref2.contained,
136
+ contained = _ref2$contained === void 0 ? false : _ref2$contained,
137
+ iconSize = _ref2.iconSize,
138
+ leftOverflowButtonProps = _ref2.leftOverflowButtonProps,
139
+ light = _ref2.light,
140
+ rightOverflowButtonProps = _ref2.rightOverflowButtonProps,
141
+ _ref2$scrollDebounceW = _ref2.scrollDebounceWait,
142
+ scrollDebounceWait = _ref2$scrollDebounceW === void 0 ? 200 : _ref2$scrollDebounceW,
143
+ scrollIntoView = _ref2.scrollIntoView,
144
+ rest = _objectWithoutProperties(_ref2, _excluded);
145
+
146
+ var _React$useContext = React__default.useContext(TabsContext),
147
+ activeIndex = _React$useContext.activeIndex,
148
+ selectedIndex = _React$useContext.selectedIndex,
149
+ setSelectedIndex = _React$useContext.setSelectedIndex,
150
+ setActiveIndex = _React$useContext.setActiveIndex;
151
+
152
+ var prefix = usePrefix();
153
+ var ref = useRef(null);
154
+ var previousButton = useRef(null);
155
+ var nextButton = useRef(null);
156
+
157
+ var _useState3 = useState(false),
158
+ _useState4 = _slicedToArray(_useState3, 2),
159
+ isScrollable = _useState4[0],
160
+ setIsScrollable = _useState4[1];
161
+
162
+ var _useState5 = useState(null),
163
+ _useState6 = _slicedToArray(_useState5, 2),
164
+ scrollLeft = _useState6[0],
165
+ setScrollLeft = _useState6[1];
166
+
167
+ var className = cx("".concat(prefix, "--tabs"), customClassName, (_cx = {}, _defineProperty(_cx, "".concat(prefix, "--tabs--contained"), contained), _defineProperty(_cx, "".concat(prefix, "--tabs--light"), light), _defineProperty(_cx, "".concat(prefix, "--tabs__icon--default"), iconSize === 'default'), _defineProperty(_cx, "".concat(prefix, "--tabs__icon--lg"), iconSize === 'lg'), _cx)); // Previous Button
168
+ // VISIBLE IF:
169
+ // SCROLLABLE
170
+ // AND SCROLL_LEFT > 0
171
+
172
+ var buttonWidth = 44;
173
+ var isPreviousButtonVisible = ref.current ? isScrollable && scrollLeft > 0 : false; // Next Button
174
+ // VISIBLE IF:
175
+ // SCROLLABLE
176
+ // AND SCROLL_LEFT + CLIENT_WIDTH < SCROLL_WIDTH
177
+
178
+ var isNextButtonVisible = ref.current ? scrollLeft + buttonWidth + ref.current.clientWidth < ref.current.scrollWidth : false;
179
+ var previousButtonClasses = cx("".concat(prefix, "--tab--overflow-nav-button"), "".concat(prefix, "--tab--overflow-nav-button--previous"), _defineProperty({}, "".concat(prefix, "--tab--overflow-nav-button--hidden"), !isPreviousButtonVisible));
180
+ var nextButtonClasses = cx("".concat(prefix, "--tab--overflow-nav-button"), "".concat(prefix, "--tab--overflow-nav-button--next"), _defineProperty({}, "".concat(prefix, "--tab--overflow-nav-button--hidden"), !isNextButtonVisible));
181
+ var tabs = useRef([]);
182
+ var debouncedOnScroll = useCallback(function () {
183
+ return debounce(function (event) {
184
+ setScrollLeft(event.target.scrollLeft);
185
+ }, scrollDebounceWait);
186
+ }, [scrollDebounceWait]);
187
+
188
+ function onKeyDown(event) {
189
+ if (matches(event, [ArrowRight, ArrowLeft, Home, End])) {
190
+ event.preventDefault();
191
+ var activeTabs = tabs.current.filter(function (tab) {
192
+ return !tab.disabled;
193
+ });
194
+ var currentIndex = activeTabs.indexOf(tabs.current[activation === 'automatic' ? selectedIndex : activeIndex]);
195
+ var nextIndex = tabs.current.indexOf(activeTabs[getNextIndex(event, activeTabs.length, currentIndex)]);
98
196
 
99
- if (match(evt, ArrowRight)) {
100
- return 1;
197
+ if (activation === 'automatic') {
198
+ setSelectedIndex(nextIndex);
199
+ } else if (activation === 'manual') {
200
+ setActiveIndex(nextIndex);
101
201
  }
102
202
 
103
- return 0;
104
- });
105
-
106
- _defineProperty(_assertThisInitialized(_this), "getTabAt", function (index, useFresh) {
107
- return !useFresh && _this["tab".concat(index)] || React__default.Children.toArray(_this.props.children)[index];
108
- });
109
-
110
- _defineProperty(_assertThisInitialized(_this), "scrollTabIntoView", function (event, _ref) {
111
- var index = _ref.index;
112
-
113
- var tab = _this.getTabAt(index);
114
-
115
- if (matches(event, [ArrowLeft, ArrowRight]) || event.type === 'click') {
116
- var _tab$tabAnchor, _tab$tabAnchor2;
117
-
118
- var currentScrollLeft = _this.state.tablistScrollLeft;
119
- tab === null || tab === void 0 ? void 0 : (_tab$tabAnchor = tab.tabAnchor) === null || _tab$tabAnchor === void 0 ? void 0 : _tab$tabAnchor.scrollIntoView({
120
- block: 'nearest',
121
- inline: 'nearest'
122
- });
123
- tab === null || tab === void 0 ? void 0 : (_tab$tabAnchor2 = tab.tabAnchor) === null || _tab$tabAnchor2 === void 0 ? void 0 : _tab$tabAnchor2.focus();
124
- var newScrollLeft = _this.tablist.current.scrollLeft;
125
-
126
- if (newScrollLeft > currentScrollLeft) {
127
- _this.tablist.current.scrollLeft += _this.OVERFLOW_BUTTON_OFFSET;
128
- }
129
- }
130
- });
203
+ tabs.current[nextIndex].focus();
204
+ }
205
+ }
131
206
 
132
- _defineProperty(_assertThisInitialized(_this), "selectTabAt", function (event, _ref2) {
133
- var index = _ref2.index,
134
- onSelectionChange = _ref2.onSelectionChange;
207
+ useEffectOnce(function () {
208
+ var tab = tabs.current[selectedIndex];
135
209
 
136
- _this.scrollTabIntoView(event, {
137
- index: index
210
+ if (scrollIntoView && tab) {
211
+ tab.scrollIntoView({
212
+ block: 'nearest',
213
+ inline: 'nearest'
214
+ });
215
+ }
216
+ });
217
+ useEffectOnce(function () {
218
+ if (tabs.current[selectedIndex].disabled) {
219
+ var activeTabs = tabs.current.filter(function (tab) {
220
+ return !tab.disabled;
138
221
  });
139
222
 
140
- if (_this.state.selected !== index) {
141
- _this.setState({
142
- selected: index
143
- });
144
-
145
- if (typeof onSelectionChange === 'function') {
146
- onSelectionChange(index);
147
- }
223
+ if (activeTabs.length > 0) {
224
+ var tab = activeTabs[0];
225
+ setSelectedIndex(tabs.current.indexOf(tab));
148
226
  }
149
- });
150
-
151
- _defineProperty(_assertThisInitialized(_this), "handleTabKeyDown", function (onSelectionChange) {
152
- return function (index, evt) {
153
- if (matches(evt, [Enter, Space])) {
154
- _this.selectTabAt(evt, {
155
- index: index,
156
- onSelectionChange: onSelectionChange
157
- });
158
- }
159
-
160
- var nextIndex = function () {
161
- if (matches(evt, [ArrowLeft, ArrowRight])) {
162
- return _this.getNextIndex(index, _this.getDirection(evt));
163
- }
164
-
165
- if (match(evt, Home)) {
166
- return 0;
167
- }
168
-
169
- if (match(evt, End)) {
170
- return _this.getEnabledTabs().pop();
171
- }
172
- }();
173
-
174
- var tab = _this.getTabAt(nextIndex);
175
-
176
- if (matches(evt, [ArrowLeft, ArrowRight, Home, End])) {
177
- var _tab$tabAnchor3;
178
-
179
- evt.preventDefault();
180
-
181
- if (_this.props.selectionMode !== 'manual') {
182
- _this.selectTabAt(evt, {
183
- index: nextIndex,
184
- onSelectionChange: onSelectionChange
185
- });
186
- } else {
187
- _this.scrollTabIntoView(evt, {
188
- index: nextIndex
189
- });
190
- }
191
-
192
- tab === null || tab === void 0 ? void 0 : (_tab$tabAnchor3 = tab.tabAnchor) === null || _tab$tabAnchor3 === void 0 ? void 0 : _tab$tabAnchor3.focus();
193
- }
194
- };
195
- });
227
+ }
228
+ });
229
+ useIsomorphicEffect(function () {
230
+ if (ref.current) {
231
+ setIsScrollable(ref.current.scrollWidth > ref.current.clientWidth);
232
+ }
196
233
 
197
- _defineProperty(_assertThisInitialized(_this), "getTabs", function () {
198
- return React__default.Children.map(_this.props.children, function (tab) {
199
- return tab;
200
- });
201
- });
234
+ function handler() {
235
+ if (ref.current) {
236
+ setIsScrollable(ref.current.scrollWidth > ref.current.clientWidth);
237
+ }
238
+ }
202
239
 
203
- _defineProperty(_assertThisInitialized(_this), "handleTabClick", function (onSelectionChange) {
204
- return function (index, evt) {
205
- evt.preventDefault();
240
+ var debouncedHandler = debounce(handler, 200);
241
+ window.addEventListener('resize', debouncedHandler);
242
+ return function () {
243
+ debouncedHandler.cancel();
244
+ window.removeEventListener('resize', debouncedHandler);
245
+ };
246
+ }, []); // updates scroll location for all scroll behavior.
247
+
248
+ useIsomorphicEffect(function () {
249
+ if (scrollLeft !== null) {
250
+ ref.current.scrollLeft = scrollLeft;
251
+ }
252
+ }, [scrollLeft]);
253
+ useIsomorphicEffect(function () {
254
+ if (!isScrollable) {
255
+ return;
256
+ }
206
257
 
207
- _this.selectTabAt(evt, {
208
- index: index,
209
- onSelectionChange: onSelectionChange
210
- });
211
- };
212
- });
258
+ var tab = activation === 'manual' ? tabs.current[activeIndex] : tabs.current[selectedIndex];
213
259
 
214
- _defineProperty(_assertThisInitialized(_this), "setTabAt", function (index, tabRef) {
215
- _this["tab".concat(index)] = tabRef;
216
- });
260
+ if (tab) {
261
+ // The width of the "scroll buttons"
262
+ // The start and end position of the selected tab
263
+ var _tab$getBoundingClien = tab.getBoundingClientRect(),
264
+ tabWidth = _tab$getBoundingClien.width;
217
265
 
218
- _defineProperty(_assertThisInitialized(_this), "overflowNavInterval", null);
266
+ var start = tab.offsetLeft;
267
+ var end = tab.offsetLeft + tabWidth; // The start and end of the visible area for the tabs
219
268
 
220
- _defineProperty(_assertThisInitialized(_this), "handleOverflowNavClick", function (_, _ref3) {
221
- var _this$tablist2;
269
+ var visibleStart = ref.current.scrollLeft + buttonWidth;
270
+ var visibleEnd = ref.current.scrollLeft + ref.current.clientWidth - buttonWidth; // The beginning of the tab is clipped and not visible
222
271
 
223
- var direction = _ref3.direction,
224
- _ref3$multiplier = _ref3.multiplier,
225
- multiplier = _ref3$multiplier === void 0 ? 10 : _ref3$multiplier;
272
+ if (start < visibleStart) {
273
+ setScrollLeft(start - buttonWidth);
274
+ } // The end of teh tab is clipped and not visible
226
275
 
227
- // account for overflow button appearing and causing tablist width change
228
- var _this$tablist$current2 = (_this$tablist2 = _this.tablist) === null || _this$tablist2 === void 0 ? void 0 : _this$tablist2.current,
229
- clientWidth = _this$tablist$current2.clientWidth,
230
- scrollLeft = _this$tablist$current2.scrollLeft,
231
- scrollWidth = _this$tablist$current2.scrollWidth;
232
276
 
233
- if (direction === 1 && !scrollLeft) {
234
- _this.tablist.current.scrollLeft += _this.OVERFLOW_BUTTON_OFFSET;
277
+ if (end > visibleEnd) {
278
+ setScrollLeft(end + buttonWidth - ref.current.clientWidth);
235
279
  }
280
+ }
281
+ }, [activation, activeIndex, selectedIndex, isScrollable]);
282
+ usePressable(previousButton, {
283
+ onPress: function onPress(_ref3) {
284
+ var longPress = _ref3.longPress;
236
285
 
237
- _this.tablist.current.scrollLeft += direction * multiplier;
238
- var leftEdgeReached = direction === -1 && scrollLeft < _this.OVERFLOW_BUTTON_OFFSET;
239
- var rightEdgeReached = direction === 1 && scrollLeft + clientWidth >= scrollWidth - _this.OVERFLOW_BUTTON_OFFSET;
240
-
241
- if (leftEdgeReached || rightEdgeReached) {
242
- if (leftEdgeReached) {
243
- var _this$rightOverflowNa, _this$rightOverflowNa2;
244
-
245
- (_this$rightOverflowNa = _this.rightOverflowNavButton) === null || _this$rightOverflowNa === void 0 ? void 0 : (_this$rightOverflowNa2 = _this$rightOverflowNa.current) === null || _this$rightOverflowNa2 === void 0 ? void 0 : _this$rightOverflowNa2.focus();
246
- }
247
-
248
- if (rightEdgeReached) {
249
- var _this$leftOverflowNav, _this$leftOverflowNav2;
250
-
251
- (_this$leftOverflowNav = _this.leftOverflowNavButton) === null || _this$leftOverflowNav === void 0 ? void 0 : (_this$leftOverflowNav2 = _this$leftOverflowNav.current) === null || _this$leftOverflowNav2 === void 0 ? void 0 : _this$leftOverflowNav2.focus();
252
- }
286
+ if (!longPress) {
287
+ setScrollLeft(Math.max(scrollLeft - ref.current.scrollWidth / tabs.current.length * 1.5, 0));
253
288
  }
254
- });
255
-
256
- _defineProperty(_assertThisInitialized(_this), "handleOverflowNavMouseDown", function (event, _ref4) {
257
- var direction = _ref4.direction;
289
+ },
290
+ onLongPress: function onLongPress() {
291
+ return createLongPressBehavior(ref, 'backward', setScrollLeft);
292
+ }
293
+ });
294
+ usePressable(nextButton, {
295
+ onPress: function onPress(_ref4) {
296
+ var longPress = _ref4.longPress;
258
297
 
259
- // disregard mouse buttons aside from left mouse button
260
- if (event.buttons !== 1) {
261
- return;
298
+ if (!longPress) {
299
+ setScrollLeft(Math.min(scrollLeft + ref.current.scrollWidth / tabs.current.length * 1.5, ref.current.scrollWidth - ref.current.clientWidth));
262
300
  }
301
+ },
302
+ onLongPress: function onLongPress() {
303
+ return createLongPressBehavior(ref, 'forward', setScrollLeft);
304
+ }
305
+ });
306
+ return /*#__PURE__*/React__default.createElement("div", {
307
+ className: className
308
+ }, /*#__PURE__*/React__default.createElement("button", _extends({
309
+ "aria-hidden": "true",
310
+ "aria-label": "Scroll left",
311
+ ref: previousButton,
312
+ className: previousButtonClasses,
313
+ type: "button"
314
+ }, leftOverflowButtonProps), _ChevronLeft || (_ChevronLeft = /*#__PURE__*/React__default.createElement(ChevronLeft, null))), /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
315
+ "aria-label": label,
316
+ ref: ref,
317
+ role: "tablist",
318
+ className: "".concat(prefix, "--tab--list"),
319
+ onScroll: debouncedOnScroll,
320
+ onKeyDown: onKeyDown
321
+ }), React__default.Children.map(children, function (child, index) {
322
+ return /*#__PURE__*/React__default.createElement(TabContext.Provider, {
323
+ value: index
324
+ }, /*#__PURE__*/React__default.cloneElement(child, {
325
+ ref: function ref(node) {
326
+ tabs.current[index] = node;
327
+ }
328
+ }));
329
+ })), /*#__PURE__*/React__default.createElement("button", _extends({
330
+ "aria-hidden": "true",
331
+ "aria-label": "Scroll right",
332
+ ref: nextButton,
333
+ className: nextButtonClasses,
334
+ type: "button"
335
+ }, rightOverflowButtonProps), _ChevronRight || (_ChevronRight = /*#__PURE__*/React__default.createElement(ChevronRight, null))));
336
+ }
337
+
338
+ TabList.propTypes = {
339
+ /**
340
+ * Specify whether the content tab should be activated automatically or
341
+ * manually
342
+ */
343
+ activation: PropTypes.oneOf(['automatic', 'manual']),
263
344
 
264
- _this.overflowNavInterval = setInterval(function () {
265
- var _this$tablist3;
266
-
267
- var _this$tablist$current3 = (_this$tablist3 = _this.tablist) === null || _this$tablist3 === void 0 ? void 0 : _this$tablist3.current,
268
- clientWidth = _this$tablist$current3.clientWidth,
269
- scrollLeft = _this$tablist$current3.scrollLeft,
270
- scrollWidth = _this$tablist$current3.scrollWidth; // clear interval if scroll reaches left or right edge
271
-
272
-
273
- var leftEdgeReached = direction === -1 && scrollLeft < _this.OVERFLOW_BUTTON_OFFSET;
274
- var rightEdgeReached = direction === 1 && scrollLeft + clientWidth >= scrollWidth - _this.OVERFLOW_BUTTON_OFFSET;
275
-
276
- if (leftEdgeReached || rightEdgeReached) {
277
- clearInterval(_this.overflowNavInterval);
278
- } // account for overflow button appearing and causing tablist width change
279
-
280
-
281
- _this.handleOverflowNavClick(event, {
282
- direction: direction
283
- });
284
- });
285
- });
286
-
287
- _defineProperty(_assertThisInitialized(_this), "handleOverflowNavMouseUp", function () {
288
- clearInterval(_this.overflowNavInterval);
289
- });
345
+ /**
346
+ * Provide an accessible label to be read when a user interacts with this
347
+ * component
348
+ */
349
+ 'aria-label': PropTypes.string.isRequired,
290
350
 
291
- return _this;
292
- }
351
+ /**
352
+ * Provide child elements to be rendered inside of `ContentTabs`.
353
+ * These elements should render a `ContentTab`
354
+ */
355
+ children: PropTypes.node,
293
356
 
294
- _createClass(Tabs, [{
295
- key: "componentDidMount",
296
- value: function componentDidMount() {
297
- var _this$tablist4;
357
+ /**
358
+ * Specify an optional className to be added to the container node
359
+ */
360
+ className: PropTypes.string,
298
361
 
299
- if (!this._debouncedHandleWindowResize) {
300
- this._debouncedHandleWindowResize = debounce(this._handleWindowResize, 200);
301
- }
362
+ /**
363
+ * Specify whether component is contained type
364
+ */
365
+ contained: PropTypes.bool,
302
366
 
303
- this._handleWindowResize();
367
+ /**
368
+ * If using `IconTab`, specify the size of the icon being used.
369
+ */
370
+ iconSize: PropTypes.oneOf(['default', 'lg']),
304
371
 
305
- window.addEventListener('resize', this._debouncedHandleWindowResize);
372
+ /**
373
+ * Provide the props that describe the left overflow button
374
+ */
375
+ leftOverflowButtonProps: PropTypes.object,
306
376
 
307
- if (!this._debouncedHandleScroll) {
308
- this._debouncedHandleScroll = debounce(this._handleScroll, this.props.scrollDebounceWait);
309
- } // scroll selected tab into view on mount
377
+ /**
378
+ * Specify whether or not to use the light component variant
379
+ */
380
+ light: PropTypes.bool,
310
381
 
382
+ /**
383
+ * Provide the props that describe the right overflow button
384
+ */
385
+ rightOverflowButtonProps: PropTypes.object,
311
386
 
312
- var _ref5 = ((_this$tablist4 = this.tablist) === null || _this$tablist4 === void 0 ? void 0 : _this$tablist4.current) || {},
313
- tablistClientWidth = _ref5.clientWidth,
314
- tablistScrollLeft = _ref5.scrollLeft,
315
- tablistScrollWidth = _ref5.scrollWidth;
387
+ /**
388
+ * Optionally provide a delay (in milliseconds) passed to the lodash
389
+ * debounce of the onScroll handler. This will impact the responsiveness
390
+ * of scroll arrow buttons rendering when scrolling to the first or last tab.
391
+ */
392
+ scrollDebounceWait: PropTypes.number,
316
393
 
317
- var tab = this.getTabAt(this.state.selected);
318
- var horizontalOverflow = tablistScrollWidth > tablistClientWidth;
394
+ /**
395
+ * Choose whether or not to automatically scroll to newly selected tabs
396
+ * on component rerender
397
+ */
398
+ scrollIntoView: PropTypes.bool
399
+ };
400
+ /**
401
+ * Helper function to setup the behavior when a button is "long pressed". This
402
+ * function will take a ref to the tablist, a direction, and a setter for
403
+ * scrollLeft and will update the scroll position within a
404
+ * requestAnimationFrame.
405
+ *
406
+ * It returns a cleanup function to be run when the long press is
407
+ * deactivated
408
+ *
409
+ * @param {RefObject} ref
410
+ * @param {'forward' | 'backward'} direction
411
+ * @param {Function} setScrollLeft
412
+ * @returns {Function}
413
+ */
319
414
 
320
- if (horizontalOverflow) {
321
- var _tab$tabAnchor4, _tab$tabAnchor5, _tab$tabAnchor6;
415
+ function createLongPressBehavior(ref, direction, setScrollLeft) {
416
+ // We manually override the scroll behavior to be "auto". If it is set as
417
+ // smooth, this animation does not update correctly
418
+ var defaultScrollBehavior = ref.current.style['scroll-behavior'];
419
+ ref.current.style['scroll-behavior'] = 'auto';
420
+ var scrollDelta = direction === 'forward' ? 5 : -5;
421
+ var frameId = null;
422
+
423
+ function tick() {
424
+ ref.current.scrollLeft = ref.current.scrollLeft + scrollDelta;
425
+ frameId = requestAnimationFrame(tick);
426
+ }
322
427
 
323
- var leftOverflowNavButtonHidden = (tab === null || tab === void 0 ? void 0 : (_tab$tabAnchor4 = tab.tabAnchor) === null || _tab$tabAnchor4 === void 0 ? void 0 : _tab$tabAnchor4.getBoundingClientRect().right) < (tab === null || tab === void 0 ? void 0 : (_tab$tabAnchor5 = tab.tabAnchor) === null || _tab$tabAnchor5 === void 0 ? void 0 : _tab$tabAnchor5.offsetParent.getBoundingClientRect().right);
324
- var rightOverflowNavButtonHidden = tablistScrollLeft + tablistClientWidth === tablistScrollWidth;
325
- this.props.scrollIntoView && (tab === null || tab === void 0 ? void 0 : (_tab$tabAnchor6 = tab.tabAnchor) === null || _tab$tabAnchor6 === void 0 ? void 0 : _tab$tabAnchor6.scrollIntoView({
326
- block: 'nearest',
327
- inline: 'nearest'
328
- })); // account for overflow buttons in scroll position on mount
428
+ frameId = requestAnimationFrame(tick);
429
+ return function () {
430
+ // Restore the previous scroll behavior
431
+ ref.current.style['scroll-behavior'] = defaultScrollBehavior; // Make sure that our `scrollLeft` value is in sync with the existing
432
+ // `ref` after our requestAnimationFrame loop above
329
433
 
330
- if (!leftOverflowNavButtonHidden && !rightOverflowNavButtonHidden) {
331
- this.tablist.current.scrollLeft += this.OVERFLOW_BUTTON_OFFSET * 2;
332
- }
333
- }
334
- }
335
- }, {
336
- key: "componentWillUnmount",
337
- value: function componentWillUnmount() {
338
- if (this._debouncedHandleWindowResize) {
339
- this._debouncedHandleWindowResize.cancel();
340
- }
434
+ setScrollLeft(ref.current.scrollLeft);
341
435
 
342
- window.removeEventListener('resize', this._debouncedHandleWindowResize);
436
+ if (frameId) {
437
+ cancelAnimationFrame(frameId);
343
438
  }
344
- }, {
345
- key: "componentDidUpdate",
346
- value: function componentDidUpdate(_, prevState) {
347
- // compare current tablist properties to current state
348
- var _this$tablist$current4 = this.tablist.current,
349
- tablistClientWidth = _this$tablist$current4.clientWidth,
350
- tablistScrollLeft = _this$tablist$current4.scrollLeft,
351
- tablistScrollWidth = _this$tablist$current4.scrollWidth;
352
- var _this$state = this.state,
353
- currentStateClientWidth = _this$state.tablistClientWidth,
354
- currentStateScrollLeft = _this$state.tablistScrollLeft,
355
- currentStateScrollWidth = _this$state.tablistScrollWidth,
356
- selected = _this$state.selected;
357
-
358
- if (tablistClientWidth !== currentStateClientWidth || tablistScrollLeft !== currentStateScrollLeft || tablistScrollWidth !== currentStateScrollWidth) {
359
- this.setState({
360
- horizontalOverflow: tablistScrollWidth > tablistClientWidth,
361
- tablistClientWidth: tablistClientWidth,
362
- tablistScrollLeft: tablistScrollLeft,
363
- tablistScrollWidth: tablistScrollWidth
364
- });
439
+ };
440
+ }
441
+
442
+ var Tab = /*#__PURE__*/React__default.forwardRef(function Tab(_ref5, ref) {
443
+ var _cx4;
444
+
445
+ var _ref5$as = _ref5.as,
446
+ BaseComponent = _ref5$as === void 0 ? 'button' : _ref5$as,
447
+ children = _ref5.children,
448
+ customClassName = _ref5.className,
449
+ disabled = _ref5.disabled,
450
+ _onClick = _ref5.onClick,
451
+ onKeyDown = _ref5.onKeyDown,
452
+ rest = _objectWithoutProperties(_ref5, _excluded2);
453
+
454
+ var prefix = usePrefix();
455
+
456
+ var _React$useContext2 = React__default.useContext(TabsContext),
457
+ selectedIndex = _React$useContext2.selectedIndex,
458
+ setSelectedIndex = _React$useContext2.setSelectedIndex,
459
+ baseId = _React$useContext2.baseId;
460
+
461
+ var index = React__default.useContext(TabContext);
462
+ var id = "".concat(baseId, "-tab-").concat(index);
463
+ var panelId = "".concat(baseId, "-tabpanel-").concat(index);
464
+ var className = cx("".concat(prefix, "--tabs__nav-item"), "".concat(prefix, "--tabs__nav-link"), customClassName, (_cx4 = {}, _defineProperty(_cx4, "".concat(prefix, "--tabs__nav-item--selected"), selectedIndex === index), _defineProperty(_cx4, "".concat(prefix, "--tabs__nav-item--disabled"), disabled), _cx4));
465
+ return /*#__PURE__*/React__default.createElement(BaseComponent, _extends({}, rest, {
466
+ "aria-controls": panelId,
467
+ "aria-disabled": disabled,
468
+ "aria-selected": selectedIndex === index,
469
+ ref: ref,
470
+ id: id,
471
+ role: "tab",
472
+ className: className,
473
+ disabled: disabled,
474
+ onClick: function onClick(evt) {
475
+ if (disabled) {
476
+ return;
365
477
  }
366
478
 
367
- if (this.props.scrollIntoView && prevState.selected !== selected) {
368
- var _this$getTabAt, _this$getTabAt$tabAnc;
479
+ setSelectedIndex(index);
369
480
 
370
- (_this$getTabAt = this.getTabAt(selected)) === null || _this$getTabAt === void 0 ? void 0 : (_this$getTabAt$tabAnc = _this$getTabAt.tabAnchor) === null || _this$getTabAt$tabAnc === void 0 ? void 0 : _this$getTabAt$tabAnc.scrollIntoView({
371
- block: 'nearest',
372
- inline: 'nearest'
373
- });
481
+ if (_onClick) {
482
+ _onClick(evt);
374
483
  }
375
- }
376
- }, {
377
- key: "render",
378
- value: function render() {
379
- var _this2 = this,
380
- _classNames,
381
- _classNames2,
382
- _classNames3;
383
-
384
- var _this$props = this.props,
385
- className = _this$props.className,
386
- type = _this$props.type,
387
- light = _this$props.light,
388
- onSelectionChange = _this$props.onSelectionChange;
389
- _this$props.scrollDebounceWait;
390
- _this$props.scrollIntoView;
391
- _this$props.selectionMode;
392
- var tabContentClassName = _this$props.tabContentClassName,
393
- leftOverflowButtonProps = _this$props.leftOverflowButtonProps,
394
- rightOverflowButtonProps = _this$props.rightOverflowButtonProps,
395
- other = _objectWithoutProperties(_this$props, _excluded);
396
-
397
- var prefix = this.context;
398
- /**
399
- * The tab panel acts like a tab panel when the screen is wider, but acts
400
- * like a select list when the screen is narrow. In the wide case we want
401
- * to allow the user to use the tab key to set the focus in the tab panel
402
- * and then use the left and right arrow keys to navigate the tabs. In the
403
- * narrow case we want to use the tab key to select different options in
404
- * the list.
405
- *
406
- * We set the tab index based on the different states so the browser will treat
407
- * the whole tab panel as a single focus component when it looks like a tab
408
- * panel and separate components when it looks like a select list.
409
- */
410
-
411
- var tabsWithProps = this.getTabs().map(function (tab, index) {
412
- var tabIndex = index === _this2.state.selected ? 0 : -1;
413
- var newTab = /*#__PURE__*/React__default.cloneElement(tab, {
414
- index: index,
415
- selected: index === _this2.state.selected,
416
- handleTabClick: _this2.handleTabClick(onSelectionChange),
417
- tabIndex: tabIndex,
418
- ref: function ref(e) {
419
- _this2.setTabAt(index, e);
420
- },
421
- handleTabKeyDown: _this2.handleTabKeyDown(onSelectionChange)
422
- });
423
- return newTab;
424
- });
425
- var tabContentWithProps = React__default.Children.map(tabsWithProps, function (tab) {
426
- var _tab$props = tab.props,
427
- tabId = _tab$props.id,
428
- children = _tab$props.children,
429
- selected = _tab$props.selected,
430
- _tab$props$renderCont = _tab$props.renderContent,
431
- Content = _tab$props$renderCont === void 0 ? TabContent : _tab$props$renderCont;
432
- return /*#__PURE__*/React__default.createElement(Content, {
433
- id: tabId && "".concat(tabId, "__panel"),
434
- className: tabContentClassName,
435
- hidden: !selected,
436
- selected: selected,
437
- "aria-labelledby": tabId
438
- }, children);
439
- });
440
- var leftOverflowNavButtonHidden = !this.state.horizontalOverflow || !this.state.tablistScrollLeft;
441
- var rightOverflowNavButtonHidden = !this.state.horizontalOverflow || this.state.tablistScrollLeft + this.state.tablistClientWidth === this.state.tablistScrollWidth;
442
- var classes = {
443
- // TODO: remove scrollable from classnames in next major release and uncomment classnames that don't contain scrollable
444
- tabs: cx(className, // `${prefix}--tabs`,
445
- "".concat(prefix, "--tabs--scrollable"), (_classNames = {}, _defineProperty(_classNames, "".concat(prefix, "--tabs--scrollable--container"), type === 'container'), _defineProperty(_classNames, "".concat(prefix, "--tabs--scrollable--light"), light), _classNames)),
446
- // TODO: remove scrollable from classnames in next major release and uncomment classnames that don't contain scrollable
447
- tablist: cx( // `${prefix}--tabs__nav`,
448
- "".concat(prefix, "--tabs--scrollable__nav")),
449
- leftOverflowButtonClasses: cx((_classNames2 = {}, _defineProperty(_classNames2, "".concat(prefix, "--tab--overflow-nav-button"), this.state.horizontalOverflow), _defineProperty(_classNames2, "".concat(prefix, "--tab--overflow-nav-button--hidden"), leftOverflowNavButtonHidden), _classNames2)),
450
- rightOverflowButtonClasses: cx((_classNames3 = {}, _defineProperty(_classNames3, "".concat(prefix, "--tab--overflow-nav-button"), this.state.horizontalOverflow), _defineProperty(_classNames3, "".concat(prefix, "--tab--overflow-nav-button--hidden"), rightOverflowNavButtonHidden), _classNames3))
451
- };
452
- return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("div", _extends({}, other, {
453
- className: classes.tabs
454
- }), /*#__PURE__*/React__default.createElement("button", _extends({
455
- "aria-hidden": "true",
456
- "aria-label": "Scroll left",
457
- className: classes.leftOverflowButtonClasses,
458
- onClick: function onClick(_) {
459
- return _this2.handleOverflowNavClick(_, {
460
- direction: -1
461
- });
462
- },
463
- onMouseDown: function onMouseDown(event) {
464
- return _this2.handleOverflowNavMouseDown(event, {
465
- direction: -1
466
- });
467
- },
468
- onMouseUp: this.handleOverflowNavMouseUp,
469
- ref: this.leftOverflowNavButton,
470
- tabIndex: "-1",
471
- type: "button"
472
- }, leftOverflowButtonProps), _ChevronLeft || (_ChevronLeft = /*#__PURE__*/React__default.createElement(ChevronLeft, null))), !leftOverflowNavButtonHidden && /*#__PURE__*/React__default.createElement("div", {
473
- className: "".concat(prefix, "--tabs__overflow-indicator--left")
474
- }), /*#__PURE__*/React__default.createElement("ul", {
475
- role: "tablist",
476
- tabIndex: -1,
477
- className: classes.tablist,
478
- ref: this.tablist,
479
- onScroll: this._debouncedHandleScroll
480
- }, tabsWithProps), !rightOverflowNavButtonHidden && /*#__PURE__*/React__default.createElement("div", {
481
- className: "".concat(prefix, "--tabs__overflow-indicator--right")
482
- }), /*#__PURE__*/React__default.createElement("button", _extends({
483
- "aria-hidden": "true",
484
- "aria-label": "Scroll right",
485
- className: classes.rightOverflowButtonClasses,
486
- onClick: function onClick(_) {
487
- return _this2.handleOverflowNavClick(_, {
488
- direction: 1
489
- });
490
- },
491
- onMouseDown: function onMouseDown(event) {
492
- return _this2.handleOverflowNavMouseDown(event, {
493
- direction: 1
494
- });
495
- },
496
- onMouseUp: this.handleOverflowNavMouseUp,
497
- ref: this.rightOverflowNavButton,
498
- tabIndex: "-1",
499
- type: "button"
500
- }, rightOverflowButtonProps), _ChevronRight || (_ChevronRight = /*#__PURE__*/React__default.createElement(ChevronRight, null)))), tabContentWithProps);
501
- }
502
- }], [{
503
- key: "getDerivedStateFromProps",
504
- value: function getDerivedStateFromProps(_ref6, state) {
505
- var selected = _ref6.selected;
506
- var prevSelected = state.prevSelected;
507
- return prevSelected === selected ? null : {
508
- selected: selected,
509
- prevSelected: selected
510
- };
511
- }
512
- /**
513
- * `scroll` event handler to save tablist clientWidth, scrollWidth, and
514
- * scrollLeft
515
- */
516
-
517
- }]);
518
-
519
- return Tabs;
520
- }(React__default.Component);
484
+ },
485
+ onKeyDown: onKeyDown,
486
+ tabIndex: selectedIndex === index ? '0' : '-1',
487
+ type: "button"
488
+ }), children);
489
+ });
490
+ Tab.propTypes = {
491
+ /**
492
+ * Provide a custom element to render instead of the default button
493
+ */
494
+ as: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
521
495
 
522
- _defineProperty(Tabs, "propTypes", {
523
496
  /**
524
- * Pass in a collection of <Tab> children to be rendered depending on the
525
- * currently selected tab
497
+ * Provide child elements to be rendered inside of `Tab`.
526
498
  */
527
499
  children: PropTypes.node,
528
500
 
529
501
  /**
530
- * Provide a className that is applied to the root <div> component for the
531
- * <Tabs>
502
+ * Specify an optional className to be added to your Tab
532
503
  */
533
504
  className: PropTypes.string,
534
505
 
535
506
  /**
536
- * Specify whether the Tab content is hidden
507
+ * Whether your Tab is disabled.
537
508
  */
538
- hidden: PropTypes.bool,
509
+ disabled: PropTypes.bool,
539
510
 
540
511
  /**
541
- * Provide the props that describe the left overflow button
512
+ * Provide a handler that is invoked when a user clicks on the control
542
513
  */
543
- leftOverflowButtonProps: PropTypes.object,
514
+ onClick: PropTypes.func,
544
515
 
545
516
  /**
546
- * Specify whether or not to use the light component variant
517
+ * Provide a handler that is invoked on the key down event for the control
547
518
  */
548
- light: PropTypes.bool,
519
+ onKeyDown: PropTypes.func,
549
520
 
521
+ /*
522
+ * An optional parameter to allow overriding the anchor rendering.
523
+ * Useful for using Tab along with react-router or other client
524
+ * side router libraries.
525
+ **/
526
+ renderButton: PropTypes.func
527
+ };
528
+ var IconTab = /*#__PURE__*/React__default.forwardRef(function IconTab(_ref6, ref) {
529
+ var children = _ref6.children,
530
+ customClassName = _ref6.className,
531
+ _ref6$defaultOpen = _ref6.defaultOpen,
532
+ defaultOpen = _ref6$defaultOpen === void 0 ? false : _ref6$defaultOpen,
533
+ enterDelayMs = _ref6.enterDelayMs,
534
+ leaveDelayMs = _ref6.leaveDelayMs,
535
+ label = _ref6.label,
536
+ rest = _objectWithoutProperties(_ref6, _excluded3);
537
+
538
+ var prefix = usePrefix();
539
+ var classNames = cx("".concat(prefix, "--tabs__nav-item--icon"), customClassName);
540
+ return /*#__PURE__*/React__default.createElement(Tooltip, {
541
+ align: "bottom",
542
+ defaultOpen: defaultOpen,
543
+ className: "".concat(prefix, "--icon-tooltip"),
544
+ enterDelayMs: enterDelayMs,
545
+ label: label,
546
+ leaveDelayMs: leaveDelayMs
547
+ }, /*#__PURE__*/React__default.createElement(Tab, _extends({
548
+ className: classNames,
549
+ ref: ref
550
+ }, rest), children));
551
+ });
552
+ IconTab.propTypes = {
550
553
  /**
551
- * Optionally provide an `onClick` handler that is invoked when a <Tab> is
552
- * clicked
554
+ * Provide an icon to be rendered inside of `IconTab` as the visual label for Tab.
553
555
  */
554
- onClick: PropTypes.func,
556
+ children: PropTypes.node,
555
557
 
556
558
  /**
557
- * Optionally provide an `onKeyDown` handler that is invoked when keyed
558
- * navigation is triggered
559
+ * Specify an optional className to be added to your Tab
559
560
  */
560
- onKeyDown: PropTypes.func,
561
+ className: PropTypes.string,
561
562
 
562
563
  /**
563
- * Provide an optional handler that is called whenever the selection
564
- * changes. This method is called with the index of the tab that was
565
- * selected
564
+ * Specify whether the tooltip for the icon should be open when it first renders
566
565
  */
567
- onSelectionChange: PropTypes.func,
566
+ defaultOpen: PropTypes.bool,
568
567
 
569
568
  /**
570
- * Provide the props that describe the right overflow button
569
+ * Specify the duration in milliseconds to delay before displaying the tooltip for the icon.
571
570
  */
572
- rightOverflowButtonProps: PropTypes.object,
571
+ enterDelayMs: PropTypes.number,
573
572
 
574
573
  /**
575
- * Optionally provide a delay (in milliseconds) passed to the lodash
576
- * debounce of the onScroll handler. This will impact the responsiveness
577
- * of scroll arrow buttons rendering when scrolling to the first or last tab.
574
+ * Provide the label to be rendered inside of the Tooltip. The label will use
575
+ * `aria-labelledby` and will fully describe the child node that is provided.
576
+ * This means that if you have text in the child node it will not be
577
+ * announced to the screen reader.
578
578
  */
579
- scrollDebounceWait: PropTypes.number,
579
+ label: PropTypes.node.isRequired,
580
580
 
581
581
  /**
582
- * Choose whether or not to automatically scroll to newly selected tabs
583
- * on component rerender
582
+ * Specify the duration in milliseconds to delay before hiding the tooltip
584
583
  */
585
- scrollIntoView: PropTypes.bool,
584
+ leaveDelayMs: PropTypes.number
585
+ };
586
+ var TabPanel = /*#__PURE__*/React__default.forwardRef(function TabPanel(_ref7, forwardRef) {
587
+ var children = _ref7.children,
588
+ customClassName = _ref7.className,
589
+ rest = _objectWithoutProperties(_ref7, _excluded4);
590
+
591
+ var prefix = usePrefix();
592
+ var panel = useRef(null);
593
+ var ref = useMergedRefs([forwardRef, panel]);
594
+
595
+ var _useState7 = useState('0'),
596
+ _useState8 = _slicedToArray(_useState7, 2),
597
+ tabIndex = _useState8[0],
598
+ setTabIndex = _useState8[1];
599
+
600
+ var _useState9 = useState(false),
601
+ _useState10 = _slicedToArray(_useState9, 2),
602
+ interactiveContent = _useState10[0],
603
+ setInteractiveContent = _useState10[1];
604
+
605
+ var _React$useContext3 = React__default.useContext(TabsContext),
606
+ selectedIndex = _React$useContext3.selectedIndex,
607
+ baseId = _React$useContext3.baseId;
608
+
609
+ var index = React__default.useContext(TabPanelContext);
610
+ var id = "".concat(baseId, "-tabpanel-").concat(index);
611
+ var tabId = "".concat(baseId, "-tab-").concat(index);
612
+ var className = cx("".concat(prefix, "--tab-content"), customClassName, _defineProperty({}, "".concat(prefix, "--tab-content--interactive"), interactiveContent));
613
+ useEffectOnce(function () {
614
+ if (!panel.current) {
615
+ return;
616
+ }
586
617
 
587
- /**
588
- * Optionally provide an index for the currently selected <Tab>
589
- */
590
- selected: PropTypes.number,
618
+ var content = getInteractiveContent(panel.current);
619
+
620
+ if (content) {
621
+ setInteractiveContent(true);
622
+ setTabIndex('-1');
623
+ }
624
+ }); // tabindex should only be 0 if no interactive content in children
625
+
626
+ useEffect(function () {
627
+ if (!panel.current) {
628
+ return;
629
+ }
630
+
631
+ var node = panel.current;
632
+
633
+ function callback() {
634
+ var content = getInteractiveContent(node);
591
635
 
636
+ if (content) {
637
+ setInteractiveContent(true);
638
+ setTabIndex('-1');
639
+ } else {
640
+ setInteractiveContent(false);
641
+ setTabIndex('0');
642
+ }
643
+ }
644
+
645
+ var observer = new MutationObserver(callback);
646
+ observer.observe(node, {
647
+ childList: true,
648
+ subtree: true
649
+ });
650
+ return function () {
651
+ observer.disconnect(node);
652
+ };
653
+ }, []);
654
+ return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
655
+ "aria-labelledby": tabId,
656
+ id: id,
657
+ className: className,
658
+ ref: ref,
659
+ role: "tabpanel",
660
+ tabIndex: tabIndex,
661
+ hidden: selectedIndex !== index
662
+ }), children);
663
+ });
664
+ TabPanel.propTypes = {
592
665
  /**
593
- * Choose whether or not to automatically change selection on focus
666
+ * Provide child elements to be rendered inside of `TabPanel`.
594
667
  */
595
- selectionMode: PropTypes.oneOf(['automatic', 'manual']),
668
+ children: PropTypes.node,
596
669
 
597
670
  /**
598
- * Provide a className that is applied to the <TabContent> components
671
+ * Specify an optional className to be added to TabPanel.
599
672
  */
600
- tabContentClassName: PropTypes.string,
601
-
673
+ className: PropTypes.string
674
+ };
675
+
676
+ function TabPanels(_ref8) {
677
+ var children = _ref8.children;
678
+ return React__default.Children.map(children, function (child, index) {
679
+ return /*#__PURE__*/React__default.createElement(TabPanelContext.Provider, {
680
+ value: index
681
+ }, child);
682
+ });
683
+ }
684
+
685
+ TabPanels.propTypes = {
602
686
  /**
603
- * Provide the type of Tab
687
+ * Provide child elements to be rendered inside of `TabPanels`.
604
688
  */
605
- type: PropTypes.oneOf(['default', 'container'])
606
- });
607
-
608
- _defineProperty(Tabs, "defaultProps", {
609
- type: 'default',
610
- scrollIntoView: true,
611
- selected: 0,
612
- selectionMode: 'automatic',
613
- scrollDebounceWait: 150
614
- });
615
-
616
- _defineProperty(Tabs, "contextType", PrefixContext);
689
+ children: PropTypes.node
690
+ };
617
691
 
618
- export { Tabs as default };
692
+ export { IconTab, Tab, TabList, TabPanel, TabPanels, Tabs };