@auth0/quantum-product 2.10.8 → 2.11.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 (31) hide show
  1. package/dropdown-menu/dropdown-menu-list-item/dropdown-menu-list-item.js +2 -1
  2. package/dropdown-menu/dropdown-menu.js +1 -1
  3. package/esm/dropdown-menu/dropdown-menu-list-item/dropdown-menu-list-item.js +2 -1
  4. package/esm/dropdown-menu/dropdown-menu.js +1 -1
  5. package/esm/tabs/tab/tab-override.js +18 -7
  6. package/esm/tabs/tab-list/tab-list-overrides.js +94 -0
  7. package/esm/tabs/tab-list/tab-list-utils.js +29 -0
  8. package/esm/tabs/tab-list/tab-list.js +111 -10
  9. package/esm/tabs/tab-list/use-tab-list-indicator/index.js +189 -0
  10. package/esm/tabs/tab-list/use-tab-list-keyboard/index.js +56 -0
  11. package/esm/tabs/tab-list/use-tab-list-overflow/index.js +149 -0
  12. package/esm/tabs/tabs-overrides.js +6 -7
  13. package/esm/tabs/tabs.js +12 -20
  14. package/package.json +6 -1
  15. package/tabs/tab/tab-override.d.ts +1 -1
  16. package/tabs/tab/tab-override.js +18 -7
  17. package/tabs/tab-list/tab-list-overrides.d.ts +12 -0
  18. package/tabs/tab-list/tab-list-overrides.js +97 -0
  19. package/tabs/tab-list/tab-list-utils.d.ts +32 -0
  20. package/tabs/tab-list/tab-list-utils.js +70 -0
  21. package/tabs/tab-list/tab-list.d.ts +9 -2
  22. package/tabs/tab-list/tab-list.js +111 -11
  23. package/tabs/tab-list/use-tab-list-indicator/index.d.ts +26 -0
  24. package/tabs/tab-list/use-tab-list-indicator/index.js +226 -0
  25. package/tabs/tab-list/use-tab-list-keyboard/index.d.ts +13 -0
  26. package/tabs/tab-list/use-tab-list-keyboard/index.js +93 -0
  27. package/tabs/tab-list/use-tab-list-overflow/index.d.ts +25 -0
  28. package/tabs/tab-list/use-tab-list-overflow/index.js +186 -0
  29. package/tabs/tabs-overrides.d.ts +1 -1
  30. package/tabs/tabs-overrides.js +6 -7
  31. package/tabs/tabs.js +12 -20
@@ -70,7 +70,7 @@ var classes_1 = require("../../styles/classes");
70
70
  var Root = (0, styled_1.styled)(menu_1.MenuItem, { name: dropdown_menu_list_item_classes_1.dropdownMenuListItemComponentName, slot: 'Root' })(function (_a) {
71
71
  var _b, _c, _d, _e;
72
72
  var theme = _a.theme, ownerState = _a.ownerState;
73
- return (__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, theme.typography.caption), { fontWeight: theme.typography.fontWeightRegular, color: theme.tokens.color_fg_link_subtle, height: 'auto', display: 'flex', alignItems: 'center', width: '100%', padding: theme.spacing(0.5, 1), borderRadius: 6, transition: theme.transitions.create(['color', 'background-color', 'box-shadow'], {
73
+ return (__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, theme.typography.caption), { fontWeight: theme.typography.fontWeightRegular, color: theme.tokens.color_fg_link_subtle, minHeight: ownerState.isDetailed ? 'auto' : theme.spacing(4), height: 'auto', display: 'flex', alignItems: 'center', width: '100%', padding: theme.spacing(0.5, 1), borderRadius: theme.spacing(0.5), transition: theme.transitions.create(['color', 'background-color', 'box-shadow'], {
74
74
  duration: theme.transitions.duration.shortest,
75
75
  }), '&:active,&:hover': {
76
76
  color: theme.tokens.color_fg_link_subtle_hover,
@@ -97,6 +97,7 @@ var Root = (0, styled_1.styled)(menu_1.MenuItem, { name: dropdown_menu_list_item
97
97
  opacity: 1,
98
98
  color: theme.tokens.color_fg_disabled,
99
99
  } }), (ownerState.size === 'large' && {
100
+ minHeight: ownerState.isDetailed ? 'auto' : theme.spacing(5),
100
101
  padding: theme.spacing(0.75, 1.5),
101
102
  })), (ownerState.color === 'danger' && (_b = {
102
103
  color: theme.tokens.color_fg_link_danger
@@ -76,7 +76,7 @@ var Root = (0, styled_1.styled)(popover_1.Popover, { name: dropdown_menu_classes
76
76
  },
77
77
  _b["& .".concat(dropdown_menu_classes_1.dropdownMenuClasses.paper)] = __assign({
78
78
  // taken from MUI's menu component
79
- maxHeight: 'calc(100% - 96px)', minWidth: theme.typography.pxToRem(180), WebkitOverflowScrolling: 'touch', padding: theme.spacing(1), borderRadius: 8, border: "1px solid ".concat(theme.tokens.color_border_default), borderColor: theme.tokens.color_border_default, boxShadow: "0px 33px 80px rgba(0, 0, 0, 0.07), 0px 13.7866px 33.4221px rgba(0, 0, 0, 0.0503198), 0px 7.37098px 17.869px rgba(0, 0, 0, 0.0417275), 0px 4.13211px 10.0172px rgba(0, 0, 0, 0.035), 0px 2.19453px 5.32008px rgba(0, 0, 0, 0.0282725), 0px 0.913195px 2.21381px rgba(0, 0, 0, 0.0196802)" }, (ownerState.size === 'large' && {
79
+ maxHeight: 'calc(100% - 96px)', minWidth: theme.typography.pxToRem(180), WebkitOverflowScrolling: 'touch', padding: theme.spacing(1), borderRadius: theme.spacing(1.25), border: "1px solid ".concat(theme.tokens.color_border_default), borderColor: theme.tokens.color_border_default, boxShadow: "0px 33px 80px rgba(0, 0, 0, 0.07), 0px 13.7866px 33.4221px rgba(0, 0, 0, 0.0503198), 0px 7.37098px 17.869px rgba(0, 0, 0, 0.0417275), 0px 4.13211px 10.0172px rgba(0, 0, 0, 0.035), 0px 2.19453px 5.32008px rgba(0, 0, 0, 0.0282725), 0px 0.913195px 2.21381px rgba(0, 0, 0, 0.0196802)" }, (ownerState.size === 'large' && {
80
80
  padding: theme.spacing(1.5),
81
81
  minWidth: theme.typography.pxToRem(260),
82
82
  })),
@@ -31,7 +31,7 @@ import { useMergedClasses } from '../../styles/classes';
31
31
  var Root = styled(MenuItem, { name: dropdownMenuListItemComponentName, slot: 'Root' })(function (_a) {
32
32
  var _b, _c, _d, _e;
33
33
  var theme = _a.theme, ownerState = _a.ownerState;
34
- return (__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, theme.typography.caption), { fontWeight: theme.typography.fontWeightRegular, color: theme.tokens.color_fg_link_subtle, height: 'auto', display: 'flex', alignItems: 'center', width: '100%', padding: theme.spacing(0.5, 1), borderRadius: 6, transition: theme.transitions.create(['color', 'background-color', 'box-shadow'], {
34
+ return (__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, theme.typography.caption), { fontWeight: theme.typography.fontWeightRegular, color: theme.tokens.color_fg_link_subtle, minHeight: ownerState.isDetailed ? 'auto' : theme.spacing(4), height: 'auto', display: 'flex', alignItems: 'center', width: '100%', padding: theme.spacing(0.5, 1), borderRadius: theme.spacing(0.5), transition: theme.transitions.create(['color', 'background-color', 'box-shadow'], {
35
35
  duration: theme.transitions.duration.shortest,
36
36
  }), '&:active,&:hover': {
37
37
  color: theme.tokens.color_fg_link_subtle_hover,
@@ -58,6 +58,7 @@ var Root = styled(MenuItem, { name: dropdownMenuListItemComponentName, slot: 'Ro
58
58
  opacity: 1,
59
59
  color: theme.tokens.color_fg_disabled,
60
60
  } }), (ownerState.size === 'large' && {
61
+ minHeight: ownerState.isDetailed ? 'auto' : theme.spacing(5),
61
62
  padding: theme.spacing(0.75, 1.5),
62
63
  })), (ownerState.color === 'danger' && (_b = {
63
64
  color: theme.tokens.color_fg_link_danger
@@ -37,7 +37,7 @@ var Root = styled(Popover, { name: dropdownMenuComponentName, slot: 'Root' })(fu
37
37
  },
38
38
  _b["& .".concat(dropdownMenuClasses.paper)] = __assign({
39
39
  // taken from MUI's menu component
40
- maxHeight: 'calc(100% - 96px)', minWidth: theme.typography.pxToRem(180), WebkitOverflowScrolling: 'touch', padding: theme.spacing(1), borderRadius: 8, border: "1px solid ".concat(theme.tokens.color_border_default), borderColor: theme.tokens.color_border_default, boxShadow: "0px 33px 80px rgba(0, 0, 0, 0.07), 0px 13.7866px 33.4221px rgba(0, 0, 0, 0.0503198), 0px 7.37098px 17.869px rgba(0, 0, 0, 0.0417275), 0px 4.13211px 10.0172px rgba(0, 0, 0, 0.035), 0px 2.19453px 5.32008px rgba(0, 0, 0, 0.0282725), 0px 0.913195px 2.21381px rgba(0, 0, 0, 0.0196802)" }, (ownerState.size === 'large' && {
40
+ maxHeight: 'calc(100% - 96px)', minWidth: theme.typography.pxToRem(180), WebkitOverflowScrolling: 'touch', padding: theme.spacing(1), borderRadius: theme.spacing(1.25), border: "1px solid ".concat(theme.tokens.color_border_default), borderColor: theme.tokens.color_border_default, boxShadow: "0px 33px 80px rgba(0, 0, 0, 0.07), 0px 13.7866px 33.4221px rgba(0, 0, 0, 0.0503198), 0px 7.37098px 17.869px rgba(0, 0, 0, 0.0417275), 0px 4.13211px 10.0172px rgba(0, 0, 0, 0.035), 0px 2.19453px 5.32008px rgba(0, 0, 0, 0.0282725), 0px 0.913195px 2.21381px rgba(0, 0, 0, 0.0196802)" }, (ownerState.size === 'large' && {
41
41
  padding: theme.spacing(1.5),
42
42
  minWidth: theme.typography.pxToRem(260),
43
43
  })),
@@ -15,10 +15,18 @@ export var createMuiTabOverrides = function (_a) {
15
15
  ],
16
16
  styleOverrides: {
17
17
  root: (_b = {
18
- paddingLeft: spacing(0.5),
19
- paddingRight: spacing(0.5),
20
- margin: spacing(0, 1.5),
21
- minWidth: 'unset'
18
+ position: 'relative',
19
+ zIndex: 1,
20
+ padding: spacing(0.75),
21
+ marginRight: 0,
22
+ height: spacing(4),
23
+ minHeight: spacing(4),
24
+ minWidth: 'unset',
25
+ transition: 'background-color 0.25s cubic-bezier(0, 0, 0.2, 1)',
26
+ '@media (prefers-reduced-motion: reduce)': {
27
+ transition: 'none',
28
+ },
29
+ borderRadius: spacing(0.5)
22
30
  },
23
31
  _b[breakpoints.up('sm')] = {
24
32
  minWidth: 'unset',
@@ -28,17 +36,20 @@ export var createMuiTabOverrides = function (_a) {
28
36
  },
29
37
  _b),
30
38
  textColorPrimary: (_c = {},
39
+ _c["&.".concat(tabClasses.disabled)] = {
40
+ color: tokens.color_fg_disabled,
41
+ },
31
42
  _c["&.".concat(tabClasses.selected)] = {
32
- color: tokens.color_fg_selected,
43
+ color: tokens.color_fg_bold,
33
44
  },
34
45
  _c['&:hover'] = {
35
- color: tokens.color_fg_selected,
46
+ color: tokens.color_fg_bold,
36
47
  },
37
48
  _c['&:focus-visible'] = {
38
49
  boxShadow: "0 0 0 2px ".concat(tokens.color_border_focus, " inset"),
39
50
  },
40
51
  _c.color = tokens.color_fg_link_subtle,
41
- _c.fontWeight = typography.fontWeightRegular,
52
+ _c.fontWeight = typography.fontWeightSemibold,
42
53
  _c),
43
54
  },
44
55
  };
@@ -0,0 +1,94 @@
1
+ import { styled } from '../../styled';
2
+ export var tabListComponentName = 'QuantumTabList';
3
+ export var TabListContainer = styled('div', {
4
+ name: tabListComponentName,
5
+ slot: 'Root',
6
+ })(function (_a) {
7
+ var theme = _a.theme;
8
+ return ({
9
+ display: 'flex',
10
+ alignItems: 'center',
11
+ position: 'relative',
12
+ isolation: 'isolate',
13
+ borderBottom: "1px solid ".concat(theme.tokens.color_border_default),
14
+ overflow: 'hidden',
15
+ });
16
+ });
17
+ export var OverflowButtonWrapper = styled('div', {
18
+ name: tabListComponentName,
19
+ slot: 'OverflowButtonWrapper',
20
+ })(function (_a) {
21
+ var theme = _a.theme;
22
+ return ({
23
+ display: 'flex',
24
+ alignItems: 'center',
25
+ marginLeft: theme.spacing(0.5),
26
+ flexShrink: 0,
27
+ height: theme.spacing(3.5),
28
+ marginBottom: theme.spacing(1),
29
+ });
30
+ });
31
+ export var OverflowLabelContainer = styled('span', {
32
+ name: tabListComponentName,
33
+ slot: 'OverflowLabelContainer',
34
+ })(function (_a) {
35
+ var theme = _a.theme;
36
+ return ({
37
+ position: 'relative',
38
+ display: 'inline-flex',
39
+ alignItems: 'center',
40
+ gap: theme.spacing(0.5),
41
+ });
42
+ });
43
+ export var OverflowLabel = styled('span', {
44
+ name: tabListComponentName,
45
+ slot: 'OverflowLabel',
46
+ })(function (_a) {
47
+ var theme = _a.theme;
48
+ return ({
49
+ display: 'flex',
50
+ alignItems: 'center',
51
+ justifyContent: 'space-between',
52
+ gap: theme.spacing(1),
53
+ fontSize: theme.typography.pxToRem(14),
54
+ fontWeight: theme.typography.fontWeightSemibold,
55
+ color: theme.tokens.color_fg_default,
56
+ });
57
+ });
58
+ var TIMING_FUNCTION = 'cubic-bezier(0.19, 1, 0.22, 1)';
59
+ export var SelectionIndicator = styled('span', {
60
+ name: tabListComponentName,
61
+ slot: 'SelectionIndicator',
62
+ shouldForwardProp: function (prop) { return !['ownerState'].includes(String(prop)); },
63
+ })(function (_a) {
64
+ var theme = _a.theme, _b = _a.ownerState, leftOffset = _b.leftOffset, indicatorWidth = _b.indicatorWidth, isVisible = _b.isVisible;
65
+ return ({
66
+ position: 'absolute',
67
+ top: 0,
68
+ bottom: theme.spacing(1),
69
+ left: 0,
70
+ width: indicatorWidth,
71
+ borderRadius: theme.spacing(0.5),
72
+ backgroundColor: theme.tokens.color_bg_layer_alternate_bold,
73
+ pointerEvents: 'none',
74
+ zIndex: 0,
75
+ opacity: isVisible ? 1 : 0,
76
+ transform: "translate3d(".concat(leftOffset, "px, 0, 0)"),
77
+ willChange: 'transform, width, opacity',
78
+ transition: "transform ".concat(theme.transitions.duration.short, "ms ").concat(TIMING_FUNCTION, ", width ").concat(theme.transitions.duration.short, "ms ").concat(TIMING_FUNCTION, ", opacity ").concat(theme.transitions.duration.short, "ms ").concat(TIMING_FUNCTION),
79
+ '@media (prefers-reduced-motion: reduce)': {
80
+ transition: 'none',
81
+ },
82
+ '&::before': {
83
+ content: '""',
84
+ position: 'absolute',
85
+ display: 'block',
86
+ bottom: theme.spacing(-1),
87
+ left: '50%',
88
+ transform: 'translateX(-50%)',
89
+ height: theme.spacing(0.25),
90
+ width: "calc(100% - ".concat(theme.spacing(2), ")"),
91
+ backgroundColor: theme.tokens.color_bg_brand_primary,
92
+ },
93
+ });
94
+ });
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ export var isTabChild = function (child) { return React.isValidElement(child); };
3
+ export var getResolvedChildValue = function (child, index) { var _a; return (_a = child.props.value) !== null && _a !== void 0 ? _a : index; };
4
+ export var getChildOrderValue = function (child, index) {
5
+ var _a, _b;
6
+ if (isTabChild(child)) {
7
+ return (_b = (_a = child.props.value) !== null && _a !== void 0 ? _a : child.key) !== null && _b !== void 0 ? _b : index;
8
+ }
9
+ return index;
10
+ };
11
+ // Tab selection uses identity equality for object values elsewhere in the tabs stack,
12
+ // so overflow ordering should follow the same semantics.
13
+ var areTabValuesEqual = function (left, right) { return left === right; };
14
+ export var areValueArraysEqual = function (left, right) {
15
+ if (left.length !== right.length) {
16
+ return false;
17
+ }
18
+ return left.every(function (value, index) { return areTabValuesEqual(value, right[index]); });
19
+ };
20
+ export var createOverflowState = function (_a) {
21
+ var baseVisibleTabCount = _a.baseVisibleTabCount, moreLabel = _a.moreLabel, defaultTabOrder = _a.defaultTabOrder, _b = _a.overflowCompensation, overflowCompensation = _b === void 0 ? 0 : _b, orderedTabValues = _a.orderedTabValues;
22
+ return ({
23
+ overflowCompensation: overflowCompensation,
24
+ orderedTabValues: orderedTabValues,
25
+ baselineVisibleTabCount: baseVisibleTabCount,
26
+ baselineMoreLabel: moreLabel,
27
+ baselineTabOrder: defaultTabOrder,
28
+ });
29
+ };
@@ -9,16 +9,117 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ var __rest = (this && this.__rest) || function (s, e) {
13
+ var t = {};
14
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
+ t[p] = s[p];
16
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
+ t[p[i]] = s[p[i]];
20
+ }
21
+ return t;
22
+ };
12
23
  import * as React from 'react';
13
24
  import MuiTabs from '@mui/material/Tabs';
14
- import { useTabsContext } from '../tabs-context';
15
- export var TabList = function (props) {
16
- var _a = useTabsContext(), onChange = _a.onChange, value = _a.value;
17
- var handleChange = function (_evt, newValue) {
18
- // onChange could be optional in react-router applications
19
- if (onChange) {
20
- onChange(newValue);
21
- }
22
- };
23
- return (React.createElement(MuiTabs, __assign({}, props, { onChange: onChange ? handleChange : undefined, value: value }), props.children));
25
+ import { Label } from '../../label';
26
+ import { Button } from '../../button';
27
+ import { DropdownMenu } from '../../dropdown-menu/dropdown-menu';
28
+ import { DropdownMenuList } from '../../dropdown-menu/dropdown-menu-list';
29
+ import { DropdownMenuListItem } from '../../dropdown-menu/dropdown-menu-list-item';
30
+ import { useDropdownMenuState } from '../../dropdown-menu/dropdown-menu-state';
31
+ import { useId } from '../../utils/use-id';
32
+ import { ChevronDown } from '@auth0/quantum-icons';
33
+ import useForkRef from '@mui/utils/useForkRef';
34
+ import { OverflowButtonWrapper, OverflowLabel, OverflowLabelContainer, SelectionIndicator, TabListContainer, } from './tab-list-overrides';
35
+ import { isTabChild } from './tab-list-utils';
36
+ import { useTabListIndicator } from './use-tab-list-indicator/index';
37
+ import { useTabListKeyboard } from './use-tab-list-keyboard/index';
38
+ import { useTabListOverflow } from './use-tab-list-overflow/index';
39
+ var defaultGetOverflowCountLabel = function (overflowCount) {
40
+ return "".concat(overflowCount, " more tab").concat(overflowCount === 1 ? '' : 's');
24
41
  };
42
+ export var TabList = React.forwardRef(function (_a, ref) {
43
+ var _b;
44
+ var _c = _a.maxVisibleTabs, maxVisibleTabs = _c === void 0 ? Infinity : _c, _d = _a.moreLabel, moreLabel = _d === void 0 ? 'More' : _d, _e = _a.getOverflowCountLabel, getOverflowCountLabel = _e === void 0 ? defaultGetOverflowCountLabel : _e, props = __rest(_a, ["maxVisibleTabs", "moreLabel", "getOverflowCountLabel"]);
45
+ var overflowMenuId = useId();
46
+ var _f = useDropdownMenuState({ baseId: "tab-overflow-menu-".concat(overflowMenuId) }), triggerProps = _f.triggerProps, menuProps = _f.menuProps;
47
+ var containerRef = React.useRef(null);
48
+ var handleRef = useForkRef(ref, containerRef);
49
+ var overflowRef = React.useRef(null);
50
+ var overflowButtonRef = React.useRef(null);
51
+ var _g = useTabListOverflow({
52
+ children: props.children,
53
+ maxVisibleTabs: maxVisibleTabs,
54
+ moreLabel: moreLabel,
55
+ getOverflowCountLabel: getOverflowCountLabel,
56
+ }), value = _g.value, onChange = _g.onChange, baseVisibleTabCount = _g.baseVisibleTabCount, minimumVisibleTabCount = _g.minimumVisibleTabCount, defaultTabOrder = _g.defaultTabOrder, visibleChildren = _g.visibleChildren, overflowChildren = _g.overflowChildren, hasOverflow = _g.hasOverflow, overflowCountLabel = _g.overflowCountLabel, isSelectedValueVisible = _g.isSelectedValueVisible, isSelectedValueInOverflow = _g.isSelectedValueInOverflow, handleChange = _g.handleChange, setOverflowState = _g.setOverflowState, promoteTabValue = _g.promoteTabValue;
57
+ var _h = useTabListKeyboard({
58
+ containerRef: containerRef,
59
+ overflowButtonRef: overflowButtonRef,
60
+ hasOverflow: hasOverflow,
61
+ menuId: menuProps.id,
62
+ menuOpen: menuProps.open,
63
+ }), handleTabsKeyDown = _h.handleTabsKeyDown, handleOverflowKeyDown = _h.handleOverflowKeyDown;
64
+ var indicatorState = useTabListIndicator({
65
+ containerRef: containerRef,
66
+ overflowRef: overflowRef,
67
+ overflowButtonRef: overflowButtonRef,
68
+ baseVisibleTabCount: baseVisibleTabCount,
69
+ minimumVisibleTabCount: minimumVisibleTabCount,
70
+ moreLabel: moreLabel,
71
+ defaultTabOrder: defaultTabOrder,
72
+ hasOverflow: hasOverflow,
73
+ visibleChildren: visibleChildren,
74
+ overflowChildrenLength: overflowChildren.length,
75
+ isSelectedValueInOverflow: isSelectedValueInOverflow,
76
+ value: value,
77
+ setOverflowState: setOverflowState,
78
+ }).indicatorState;
79
+ return (React.createElement(TabListContainer, { ref: handleRef },
80
+ React.createElement(SelectionIndicator, { className: (_b = props.classes) === null || _b === void 0 ? void 0 : _b.indicator, ownerState: {
81
+ leftOffset: indicatorState.leftOffset,
82
+ indicatorWidth: indicatorState.indicatorWidth,
83
+ isVisible: indicatorState.isVisible,
84
+ } }),
85
+ React.createElement(MuiTabs, __assign({}, props, { TabIndicatorProps: { style: { display: 'none' } }, onChange: onChange ? handleChange : undefined, onKeyDown: handleTabsKeyDown, value: isSelectedValueVisible ? value : false }), visibleChildren),
86
+ hasOverflow && (React.createElement(OverflowButtonWrapper, { ref: overflowRef },
87
+ React.createElement(Button, __assign({}, triggerProps, { ref: overflowButtonRef, "aria-controls": menuProps.open ? triggerProps['aria-controls'] : undefined, "aria-label": overflowCountLabel, "data-selected": isSelectedValueInOverflow ? 'true' : undefined, onKeyDown: handleOverflowKeyDown, label: React.createElement(OverflowLabelContainer, null,
88
+ React.createElement(OverflowLabel, null,
89
+ moreLabel,
90
+ React.createElement(Label, { color: "default" }, overflowChildren.length)),
91
+ React.createElement(ChevronDown, { size: 16, color: "currentColor" })), size: "small", variant: "link", sx: function (theme) { return ({
92
+ padding: theme.spacing(0.65, 1),
93
+ transition: 'none',
94
+ '&:hover': { background: 'transparent' },
95
+ '&:hover *': {
96
+ color: theme.tokens.color_fg_bold,
97
+ },
98
+ '&:focus': { outline: 'none' },
99
+ '&:focus-visible': {
100
+ boxShadow: "0 0 0 2px ".concat(theme.tokens.color_border_focus, " inset"),
101
+ transition: 'none',
102
+ },
103
+ }); } })),
104
+ React.createElement(DropdownMenu, __assign({}, menuProps),
105
+ React.createElement(DropdownMenuList, null, overflowChildren.map(function (child) {
106
+ if (!isTabChild(child))
107
+ return null;
108
+ var _a = child.props, label = _a.label, tabValue = _a.value, disabled = _a.disabled, tabOnClick = _a.onClick, _icon = _a.icon, _iconPosition = _a.iconPosition, _labelIcon = _a.labelIcon, _productReleaseStage = _a.productReleaseStage, _sx = _a.sx, _textColor = _a.textColor, _wrapped = _a.wrapped, overflowItemProps = __rest(_a, ["label", "value", "disabled", "onClick", "icon", "iconPosition", "labelIcon", "productReleaseStage", "sx", "textColor", "wrapped"]);
109
+ var isSelected = tabValue === value;
110
+ return (React.createElement(DropdownMenuListItem, __assign({ key: String(tabValue), title: label, selected: isSelected, disabled: disabled }, overflowItemProps, { onClick: function (event) {
111
+ if (disabled)
112
+ return;
113
+ if (tabOnClick) {
114
+ tabOnClick(event);
115
+ }
116
+ promoteTabValue(tabValue);
117
+ if (onChange) {
118
+ onChange(tabValue);
119
+ }
120
+ if (menuProps.onClose) {
121
+ menuProps.onClose({}, 'itemSelect');
122
+ }
123
+ } })));
124
+ })))))));
125
+ });
@@ -0,0 +1,189 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __read = (this && this.__read) || function (o, n) {
13
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
14
+ if (!m) return o;
15
+ var i = m.call(o), r, ar = [], e;
16
+ try {
17
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
18
+ }
19
+ catch (error) { e = { error: error }; }
20
+ finally {
21
+ try {
22
+ if (r && !r.done && (m = i["return"])) m.call(i);
23
+ }
24
+ finally { if (e) throw e.error; }
25
+ }
26
+ return ar;
27
+ };
28
+ import * as React from 'react';
29
+ import { createOverflowState } from '../tab-list-utils';
30
+ var RESIZE_SETTLE_DELAY = 120;
31
+ var HIDDEN_INDICATOR_STATE = { leftOffset: 0, indicatorWidth: 0, isVisible: false };
32
+ var getHiddenIndicatorState = function (currentValue) {
33
+ if (currentValue.isVisible === HIDDEN_INDICATOR_STATE.isVisible &&
34
+ currentValue.leftOffset === HIDDEN_INDICATOR_STATE.leftOffset &&
35
+ currentValue.indicatorWidth === HIDDEN_INDICATOR_STATE.indicatorWidth) {
36
+ return currentValue;
37
+ }
38
+ return HIDDEN_INDICATOR_STATE;
39
+ };
40
+ export var useTabListIndicator = function (_a) {
41
+ var containerRef = _a.containerRef, overflowRef = _a.overflowRef, overflowButtonRef = _a.overflowButtonRef, baseVisibleTabCount = _a.baseVisibleTabCount, minimumVisibleTabCount = _a.minimumVisibleTabCount, moreLabel = _a.moreLabel, defaultTabOrder = _a.defaultTabOrder, hasOverflow = _a.hasOverflow, visibleChildren = _a.visibleChildren, overflowChildrenLength = _a.overflowChildrenLength, isSelectedValueInOverflow = _a.isSelectedValueInOverflow, value = _a.value, setOverflowState = _a.setOverflowState;
42
+ var _b = __read(React.useState(0), 2), measurementVersion = _b[0], setMeasurementVersion = _b[1];
43
+ var _c = __read(React.useState(HIDDEN_INDICATOR_STATE), 2), indicatorState = _c[0], setIndicatorState = _c[1];
44
+ var resizeResetTimeoutRef = React.useRef();
45
+ var previousContainerWidthRef = React.useRef(null);
46
+ var clearResizeResetTimeout = React.useCallback(function () {
47
+ if (resizeResetTimeoutRef.current === undefined) {
48
+ return;
49
+ }
50
+ window.clearTimeout(resizeResetTimeoutRef.current);
51
+ resizeResetTimeoutRef.current = undefined;
52
+ }, []);
53
+ React.useLayoutEffect(function () {
54
+ if (!hasOverflow || !containerRef.current || !overflowRef.current) {
55
+ return;
56
+ }
57
+ var visibleTabs = containerRef.current.querySelectorAll('[role="tab"]');
58
+ var firstVisibleTab = visibleTabs[0];
59
+ var lastVisibleTab = visibleTabs[visibleTabs.length - 1];
60
+ if (!firstVisibleTab || !lastVisibleTab) {
61
+ return;
62
+ }
63
+ var containerRect = containerRef.current.getBoundingClientRect();
64
+ var firstVisibleTabRect = firstVisibleTab.getBoundingClientRect();
65
+ var lastVisibleTabRect = lastVisibleTab.getBoundingClientRect();
66
+ var overflowRect = overflowRef.current.getBoundingClientRect();
67
+ if (containerRect.width === 0 ||
68
+ firstVisibleTabRect.width === 0 ||
69
+ lastVisibleTabRect.width === 0 ||
70
+ overflowRect.width === 0) {
71
+ return;
72
+ }
73
+ var isClippedAtStart = firstVisibleTabRect.left < containerRect.left;
74
+ var overlapsOverflowTrigger = lastVisibleTabRect.right >= overflowRect.left;
75
+ if (isClippedAtStart || overlapsOverflowTrigger) {
76
+ setOverflowState(function (currentValue) {
77
+ var nextOverflowCompensation = Math.min(currentValue.overflowCompensation + 1, baseVisibleTabCount - minimumVisibleTabCount);
78
+ if (nextOverflowCompensation === currentValue.overflowCompensation) {
79
+ return currentValue;
80
+ }
81
+ return __assign(__assign({}, currentValue), { overflowCompensation: nextOverflowCompensation, baselineVisibleTabCount: baseVisibleTabCount, baselineMoreLabel: moreLabel, baselineTabOrder: defaultTabOrder });
82
+ });
83
+ }
84
+ }, [
85
+ baseVisibleTabCount,
86
+ containerRef,
87
+ defaultTabOrder,
88
+ measurementVersion,
89
+ minimumVisibleTabCount,
90
+ moreLabel,
91
+ hasOverflow,
92
+ overflowChildrenLength,
93
+ overflowRef,
94
+ setOverflowState,
95
+ visibleChildren,
96
+ ]);
97
+ React.useLayoutEffect(function () {
98
+ if (!containerRef.current) {
99
+ setIndicatorState(getHiddenIndicatorState);
100
+ return;
101
+ }
102
+ var selectedVisibleTab = containerRef.current.querySelector('[role="tab"][aria-selected="true"]');
103
+ var indicatorTarget = selectedVisibleTab || (isSelectedValueInOverflow ? overflowButtonRef.current : null);
104
+ if (!indicatorTarget) {
105
+ setIndicatorState(getHiddenIndicatorState);
106
+ return;
107
+ }
108
+ var containerRect = containerRef.current.getBoundingClientRect();
109
+ var targetRect = indicatorTarget.getBoundingClientRect();
110
+ if (containerRect.width === 0 || targetRect.width === 0) {
111
+ setIndicatorState(getHiddenIndicatorState);
112
+ return;
113
+ }
114
+ var nextIndicatorState = {
115
+ leftOffset: targetRect.left - containerRect.left,
116
+ indicatorWidth: targetRect.width,
117
+ isVisible: true,
118
+ };
119
+ setIndicatorState(function (currentValue) {
120
+ if (currentValue.isVisible === nextIndicatorState.isVisible &&
121
+ currentValue.leftOffset === nextIndicatorState.leftOffset &&
122
+ currentValue.indicatorWidth === nextIndicatorState.indicatorWidth) {
123
+ return currentValue;
124
+ }
125
+ return nextIndicatorState;
126
+ });
127
+ }, [
128
+ containerRef,
129
+ isSelectedValueInOverflow,
130
+ measurementVersion,
131
+ overflowButtonRef,
132
+ overflowChildrenLength,
133
+ value,
134
+ visibleChildren,
135
+ ]);
136
+ React.useLayoutEffect(function () {
137
+ if (!containerRef.current || typeof ResizeObserver === 'undefined') {
138
+ return;
139
+ }
140
+ previousContainerWidthRef.current = containerRef.current.getBoundingClientRect().width;
141
+ var observer = new ResizeObserver(function () {
142
+ var _a, _b;
143
+ var nextContainerWidth = (_b = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) !== null && _b !== void 0 ? _b : 0;
144
+ var previousContainerWidth = previousContainerWidthRef.current;
145
+ var isExpanding = previousContainerWidth !== null && nextContainerWidth > previousContainerWidth;
146
+ previousContainerWidthRef.current = nextContainerWidth;
147
+ if (isExpanding) {
148
+ clearResizeResetTimeout();
149
+ resizeResetTimeoutRef.current = window.setTimeout(function () {
150
+ setOverflowState(function (currentValue) {
151
+ if (currentValue.overflowCompensation === 0) {
152
+ return currentValue;
153
+ }
154
+ return createOverflowState({
155
+ baseVisibleTabCount: baseVisibleTabCount,
156
+ moreLabel: moreLabel,
157
+ defaultTabOrder: defaultTabOrder,
158
+ overflowCompensation: 0,
159
+ orderedTabValues: currentValue.orderedTabValues,
160
+ });
161
+ });
162
+ setMeasurementVersion(function (currentValue) { return currentValue + 1; });
163
+ resizeResetTimeoutRef.current = undefined;
164
+ }, RESIZE_SETTLE_DELAY);
165
+ }
166
+ else {
167
+ clearResizeResetTimeout();
168
+ }
169
+ setMeasurementVersion(function (currentValue) { return currentValue + 1; });
170
+ });
171
+ observer.observe(containerRef.current);
172
+ if (overflowRef.current) {
173
+ observer.observe(overflowRef.current);
174
+ }
175
+ return function () {
176
+ clearResizeResetTimeout();
177
+ observer.disconnect();
178
+ };
179
+ }, [
180
+ baseVisibleTabCount,
181
+ clearResizeResetTimeout,
182
+ containerRef,
183
+ defaultTabOrder,
184
+ moreLabel,
185
+ overflowRef,
186
+ setOverflowState,
187
+ ]);
188
+ return { indicatorState: indicatorState };
189
+ };
@@ -0,0 +1,56 @@
1
+ import * as React from 'react';
2
+ export var useTabListKeyboard = function (_a) {
3
+ var containerRef = _a.containerRef, overflowButtonRef = _a.overflowButtonRef, hasOverflow = _a.hasOverflow, menuId = _a.menuId, menuOpen = _a.menuOpen;
4
+ var shouldFocusOverflowMenuRef = React.useRef(false);
5
+ var focusLastVisibleTab = React.useCallback(function () {
6
+ var _a;
7
+ var visibleTabs = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll('[role="tab"]');
8
+ var lastVisibleTab = visibleTabs === null || visibleTabs === void 0 ? void 0 : visibleTabs[visibleTabs.length - 1];
9
+ lastVisibleTab === null || lastVisibleTab === void 0 ? void 0 : lastVisibleTab.focus();
10
+ }, [containerRef]);
11
+ var handleTabsKeyDown = React.useCallback(function (event) {
12
+ var _a;
13
+ if (!hasOverflow || !overflowButtonRef.current || event.key !== 'ArrowRight') {
14
+ return;
15
+ }
16
+ var visibleTabs = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll('[role="tab"]');
17
+ var lastVisibleTab = visibleTabs === null || visibleTabs === void 0 ? void 0 : visibleTabs[visibleTabs.length - 1];
18
+ if (lastVisibleTab && event.target === lastVisibleTab) {
19
+ event.preventDefault();
20
+ overflowButtonRef.current.focus();
21
+ }
22
+ }, [containerRef, hasOverflow, overflowButtonRef]);
23
+ var handleOverflowKeyDown = React.useCallback(function (event) {
24
+ if ((event.key === 'Enter' || event.key === ' ' || event.key === 'Spacebar') && !menuOpen) {
25
+ shouldFocusOverflowMenuRef.current = true;
26
+ }
27
+ if (event.key !== 'ArrowLeft') {
28
+ return;
29
+ }
30
+ event.preventDefault();
31
+ focusLastVisibleTab();
32
+ }, [focusLastVisibleTab, menuOpen]);
33
+ React.useEffect(function () {
34
+ if (!menuOpen || !shouldFocusOverflowMenuRef.current) {
35
+ return;
36
+ }
37
+ var focusOverflowMenuItem = function () {
38
+ var overflowMenu = document.getElementById(menuId !== null && menuId !== void 0 ? menuId : '');
39
+ if (!overflowMenu) {
40
+ return;
41
+ }
42
+ var nextFocusedItem = overflowMenu.querySelector('[role="menuitem"][aria-selected="true"]:not([aria-disabled="true"])') || overflowMenu.querySelector('[role="menuitem"]:not([aria-disabled="true"])');
43
+ if (!nextFocusedItem) {
44
+ return;
45
+ }
46
+ nextFocusedItem.focus();
47
+ shouldFocusOverflowMenuRef.current = false;
48
+ };
49
+ var frameId = window.requestAnimationFrame(focusOverflowMenuItem);
50
+ return function () { return window.cancelAnimationFrame(frameId); };
51
+ }, [menuId, menuOpen]);
52
+ return {
53
+ handleTabsKeyDown: handleTabsKeyDown,
54
+ handleOverflowKeyDown: handleOverflowKeyDown,
55
+ };
56
+ };