carbon-react 117.3.0 → 117.4.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 (22) hide show
  1. package/esm/components/tabs/__internal__/tab-title/tab-title.style.js +3 -0
  2. package/esm/components/tabs/__internal__/tabs-header/tabs-header.component.d.ts +1 -2
  3. package/esm/components/tabs/__internal__/tabs-header/tabs-header.component.js +45 -7
  4. package/esm/components/tabs/__internal__/tabs-header/tabs-header.style.d.ts +9 -2
  5. package/esm/components/tabs/__internal__/tabs-header/tabs-header.style.js +90 -17
  6. package/esm/components/tabs/tabs.component.js +2 -11
  7. package/esm/hooks/__internal__/useThrottle/index.d.ts +1 -0
  8. package/esm/hooks/__internal__/useThrottle/index.js +1 -0
  9. package/esm/hooks/__internal__/useThrottle/useThrottle.d.ts +4 -0
  10. package/esm/hooks/__internal__/useThrottle/useThrottle.js +18 -0
  11. package/lib/components/tabs/__internal__/tab-title/tab-title.style.js +3 -0
  12. package/lib/components/tabs/__internal__/tabs-header/tabs-header.component.d.ts +1 -2
  13. package/lib/components/tabs/__internal__/tabs-header/tabs-header.component.js +49 -6
  14. package/lib/components/tabs/__internal__/tabs-header/tabs-header.style.d.ts +9 -2
  15. package/lib/components/tabs/__internal__/tabs-header/tabs-header.style.js +97 -17
  16. package/lib/components/tabs/tabs.component.js +2 -11
  17. package/lib/hooks/__internal__/useThrottle/index.d.ts +1 -0
  18. package/lib/hooks/__internal__/useThrottle/index.js +15 -0
  19. package/lib/hooks/__internal__/useThrottle/package.json +6 -0
  20. package/lib/hooks/__internal__/useThrottle/useThrottle.d.ts +4 -0
  21. package/lib/hooks/__internal__/useThrottle/useThrottle.js +29 -0
  22. package/package.json +1 -1
@@ -217,6 +217,9 @@ const tabTitleStyles = css`
217
217
  text-decoration: none;
218
218
  outline-offset: 0px;
219
219
  margin: 0;
220
+ ${({
221
+ position
222
+ }) => position === "top" && "white-space: nowrap"};
220
223
 
221
224
  a:visited {
222
225
  color: inherit;
@@ -4,10 +4,9 @@ export interface TabHeaderProps {
4
4
  position?: "top" | "left";
5
5
  extendedLine?: boolean;
6
6
  noRightBorder?: boolean;
7
- alternateStyling?: boolean;
8
7
  isInSidebar?: boolean;
9
8
  children: React.ReactNode;
10
9
  align?: "left" | "right";
11
10
  }
12
- declare const TabsHeader: ({ align, children, position, role, extendedLine, alternateStyling, noRightBorder, isInSidebar, }: TabHeaderProps) => JSX.Element;
11
+ declare const TabsHeader: ({ align, children, position, role, extendedLine, noRightBorder, isInSidebar, }: TabHeaderProps) => JSX.Element;
13
12
  export default TabsHeader;
@@ -1,6 +1,20 @@
1
- import React from "react";
1
+ import React, { useRef, useState } from "react";
2
2
  import PropTypes from "prop-types";
3
- import { StyledTabsHeaderWrapper, StyledTabsHeaderList } from "./tabs-header.style";
3
+ import { StyledTabsHeaderWrapper, StyledTabsHeaderList, StyledTabsBottomBorder, StyledTabsWrapper, StyledTabsBottomBorderWrapper } from "./tabs-header.style";
4
+ import useThrottle from "../../../../hooks/__internal__/useThrottle";
5
+ /* In the original prototype the tabs have shadows that fade out as you scroll horizontally.
6
+ * This value is the closest replication to the way that the shadow disappears.
7
+ * It is ultimately tied to the position of the scroll that will then fade the shadow in and out. */
8
+
9
+ const fullOpacityThreshold = 128;
10
+
11
+ const getOpacityRatio = value => value / fullOpacityThreshold;
12
+
13
+ const getScrollRight = ({
14
+ scrollWidth,
15
+ clientWidth,
16
+ scrollLeft
17
+ }) => scrollWidth - clientWidth - scrollLeft;
4
18
 
5
19
  const TabsHeader = ({
6
20
  align = "left",
@@ -8,10 +22,31 @@ const TabsHeader = ({
8
22
  position = "top",
9
23
  role,
10
24
  extendedLine,
11
- alternateStyling,
12
25
  noRightBorder = false,
13
26
  isInSidebar = false
14
27
  }) => {
28
+ const [leftScrollOpacity, setLeftScrollOpacity] = useState(0);
29
+ const [rightScrollOpacity, setRightScrollOpacity] = useState(1);
30
+ const ref = useRef(null);
31
+ let isScrollable = false;
32
+ const {
33
+ current
34
+ } = ref;
35
+
36
+ if (position === "top" && current) {
37
+ isScrollable = current.scrollWidth > current.clientWidth;
38
+ }
39
+
40
+ const handleScroll = e => {
41
+ const {
42
+ scrollLeft
43
+ } = e.target;
44
+ const scrollRight = getScrollRight(e.target);
45
+ setLeftScrollOpacity(Math.min(getOpacityRatio(scrollLeft), 1));
46
+ setRightScrollOpacity(Math.min(getOpacityRatio(scrollRight), 1));
47
+ };
48
+
49
+ const throttledHandleScroll = useThrottle(handleScroll, 50);
15
50
  return /*#__PURE__*/React.createElement(StyledTabsHeaderWrapper, {
16
51
  isInSidebar: isInSidebar,
17
52
  position: position
@@ -20,15 +55,18 @@ const TabsHeader = ({
20
55
  position: position,
21
56
  role: role,
22
57
  extendedLine: extendedLine,
23
- alternateStyling: alternateStyling,
24
58
  noRightBorder: noRightBorder,
25
- isInSidebar: isInSidebar
26
- }, children));
59
+ isInSidebar: isInSidebar,
60
+ onScroll: throttledHandleScroll,
61
+ leftScrollOpacity: leftScrollOpacity,
62
+ rightScrollOpacity: rightScrollOpacity,
63
+ isScrollable: isScrollable,
64
+ ref: ref
65
+ }, position === "top" ? /*#__PURE__*/React.createElement(StyledTabsWrapper, null, /*#__PURE__*/React.createElement(StyledTabsBottomBorderWrapper, null, /*#__PURE__*/React.createElement(StyledTabsBottomBorder, null)), children) : children));
27
66
  };
28
67
 
29
68
  TabsHeader.propTypes = {
30
69
  "align": PropTypes.oneOf(["left", "right"]),
31
- "alternateStyling": PropTypes.bool,
32
70
  "children": PropTypes.node,
33
71
  "extendedLine": PropTypes.bool,
34
72
  "isInSidebar": PropTypes.bool,
@@ -1,6 +1,13 @@
1
1
  import { TabHeaderProps } from "./tabs-header.component";
2
2
  declare type StyledTabsHeaderWrapperProps = Pick<TabHeaderProps, "position" | "isInSidebar">;
3
3
  declare const StyledTabsHeaderWrapper: import("styled-components").StyledComponent<"div", any, StyledTabsHeaderWrapperProps, never>;
4
- export declare type StyledTabsHeaderListProps = Pick<TabHeaderProps, "align" | "alternateStyling" | "extendedLine" | "noRightBorder" | "isInSidebar" | "position">;
4
+ export interface StyledTabsHeaderListProps extends Pick<TabHeaderProps, "align" | "extendedLine" | "noRightBorder" | "isInSidebar" | "position"> {
5
+ leftScrollOpacity?: number;
6
+ rightScrollOpacity?: number;
7
+ isScrollable?: boolean;
8
+ }
5
9
  declare const StyledTabsHeaderList: import("styled-components").StyledComponent<"div", any, StyledTabsHeaderListProps, never>;
6
- export { StyledTabsHeaderWrapper, StyledTabsHeaderList };
10
+ declare const StyledTabsWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
11
+ declare const StyledTabsBottomBorderWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
12
+ declare const StyledTabsBottomBorder: import("styled-components").StyledComponent<"div", any, {}, never>;
13
+ export { StyledTabsHeaderWrapper, StyledTabsHeaderList, StyledTabsWrapper, StyledTabsBottomBorderWrapper, StyledTabsBottomBorder, };
@@ -1,17 +1,6 @@
1
1
  import styled, { css } from "styled-components";
2
-
3
- const computeLineWidth = ({
4
- alternateStyling,
5
- isInSidebar,
6
- position
7
- }) => {
8
- if (isInSidebar && position === "left") {
9
- return "0px";
10
- }
11
-
12
- return alternateStyling ? "-1px" : "-2px";
13
- };
14
-
2
+ import BaseTheme from "../../../../style/themes/base";
3
+ const outlineWidth = "3px";
15
4
  const StyledTabsHeaderWrapper = styled.div`
16
5
  ${({
17
6
  position,
@@ -32,9 +21,21 @@ const StyledTabsHeaderWrapper = styled.div`
32
21
  `}
33
22
  `}
34
23
  `;
24
+ const commonShadowStyles = css`
25
+ pointer-events: none;
26
+ content: "";
27
+ background-repeat: no-repeat;
28
+ background-size: 16px 48px;
29
+ background-attachment: scroll;
30
+ z-index: ${({
31
+ theme
32
+ }) => theme.zIndex.overlay};
33
+ position: sticky;
34
+ min-width: 16px;
35
+ transition: opacity 0.1s ease-in-out;
36
+ `;
35
37
  const StyledTabsHeaderList = styled.div`
36
38
  display: flex;
37
- box-shadow: inset 0px ${computeLineWidth} 0px 0px var(--colorsActionMinor100);
38
39
  ${({
39
40
  extendedLine = true
40
41
  }) => !extendedLine && css`
@@ -42,8 +43,57 @@ const StyledTabsHeaderList = styled.div`
42
43
  `}
43
44
  cursor: default;
44
45
  list-style: none;
45
- margin: 0;
46
- padding: 0;
46
+ margin: -${outlineWidth};
47
+ padding: ${outlineWidth};
48
+ overflow-x: auto;
49
+ position: relative;
50
+ ${({
51
+ position
52
+ }) => position === "top" && "white-space: nowrap"};
53
+
54
+ ${({
55
+ isScrollable,
56
+ leftScrollOpacity,
57
+ rightScrollOpacity
58
+ }) => isScrollable && css`
59
+ &:before {
60
+ ${commonShadowStyles}
61
+ background: radial-gradient(
62
+ farthest-side at 0 50%,
63
+ rgba(0, 0, 0, 0.2),
64
+ rgba(0, 0, 0, 0)
65
+ );
66
+ background-position: left calc(50% - 4px);
67
+ left: -${outlineWidth};
68
+ margin-right: -16px;
69
+ opacity: ${leftScrollOpacity};
70
+ }
71
+
72
+ &:after {
73
+ ${commonShadowStyles}
74
+ background: radial-gradient(
75
+ farthest-side at 100% 50%,
76
+ rgba(0, 0, 0, 0.2),
77
+ rgba(0, 0, 0, 0)
78
+ );
79
+ background-position: right calc(50% - 4px);
80
+ right: -${outlineWidth};
81
+ margin-left: -16px;
82
+ opacity: ${rightScrollOpacity};
83
+ }
84
+ `}
85
+
86
+ &::-webkit-scrollbar {
87
+ -webkit-appearance: none;
88
+ background: var(--colorsUtilityMajor025);
89
+ height: 8px;
90
+ width: 8px;
91
+ }
92
+
93
+ &::-webkit-scrollbar-thumb {
94
+ background-color: var(--colorsUtilityMajor300);
95
+ cursor: pointer;
96
+ }
47
97
 
48
98
  ${({
49
99
  align = "left"
@@ -69,4 +119,27 @@ const StyledTabsHeaderList = styled.div`
69
119
  `}
70
120
  `}
71
121
  `;
72
- export { StyledTabsHeaderWrapper, StyledTabsHeaderList };
122
+ StyledTabsHeaderList.defaultProps = {
123
+ theme: BaseTheme
124
+ };
125
+ const StyledTabsWrapper = styled.div`
126
+ position: relative;
127
+ min-width: max-content;
128
+ width: 100%;
129
+ height: 100%;
130
+ `;
131
+ const StyledTabsBottomBorderWrapper = styled.div`
132
+ position: absolute;
133
+ width: 100%;
134
+ height: auto;
135
+ bottom: 0;
136
+ `;
137
+ const StyledTabsBottomBorder = styled.div`
138
+ position: sticky;
139
+ bottom: 2px;
140
+ left: ${outlineWidth};
141
+ right: ${outlineWidth};
142
+ height: 2px;
143
+ background-color: var(--colorsActionMinor100);
144
+ `;
145
+ export { StyledTabsHeaderWrapper, StyledTabsHeaderList, StyledTabsWrapper, StyledTabsBottomBorderWrapper, StyledTabsBottomBorder };
@@ -45,7 +45,6 @@ const Tabs = ({
45
45
  }).map(() => /*#__PURE__*/createRef()), [filteredChildren.length]);
46
46
  const previousSelectedTabId = useRef(selectedTabId);
47
47
  const [selectedTabIdState, setSelectedTabIdState] = useState(selectedTabId || filteredChildren[0].props.tabId);
48
- const [tabStopId, setTabStopId] = useState();
49
48
  const {
50
49
  isInSidebar
51
50
  } = useContext(DrawerSidebarContext);
@@ -70,7 +69,6 @@ const Tabs = ({
70
69
  /** Returns true/false for if the given tab id is selected. */
71
70
 
72
71
  const isTabSelected = useCallback(tabId => tabId === selectedTabIdState, [selectedTabIdState]);
73
- const hasTabStop = useCallback(tabId => tabId === tabStopId, [tabStopId]);
74
72
  /** Updates the currently visible tab */
75
73
 
76
74
  const updateVisibleTab = useCallback(tabid => {
@@ -78,14 +76,10 @@ const Tabs = ({
78
76
  setSelectedTabIdState(tabid);
79
77
  }
80
78
 
81
- if (!hasTabStop(tabid)) {
82
- setTabStopId(tabid);
83
- }
84
-
85
79
  if (onTabChange) {
86
80
  onTabChange(tabid);
87
81
  }
88
- }, [onTabChange, isTabSelected, hasTabStop]);
82
+ }, [onTabChange, isTabSelected]);
89
83
  const blurPreviousSelectedTab = useCallback(() => {
90
84
  const {
91
85
  current
@@ -145,9 +139,7 @@ const Tabs = ({
145
139
  newIndex = 0;
146
140
  }
147
141
 
148
- const nextTabId = tabIds[newIndex];
149
142
  const nextRef = tabRefs[newIndex];
150
- updateVisibleTab(nextTabId);
151
143
  focusTab(nextRef);
152
144
  };
153
145
  /** Handles the keyboard navigation of tabs */
@@ -223,7 +215,7 @@ const Tabs = ({
223
215
  onClick: handleTabClick,
224
216
  onKeyDown: handleKeyDown(index),
225
217
  ref: tabRefs[index],
226
- tabIndex: isTabSelected(tabId) || hasTabStop(tabId) ? 0 : -1,
218
+ tabIndex: isTabSelected(tabId) ? 0 : -1,
227
219
  title: title,
228
220
  href: href,
229
221
  isTabSelected: isTabSelected(tabId),
@@ -250,7 +242,6 @@ const Tabs = ({
250
242
  position: isInSidebar ? "left" : position,
251
243
  role: "tablist",
252
244
  extendedLine: extendedLine,
253
- alternateStyling: variant === "alternate" || isInSidebar,
254
245
  noRightBorder: ["no right side", "no sides"].includes(borders),
255
246
  isInSidebar: isInSidebar
256
247
  }, tabTitles);
@@ -0,0 +1 @@
1
+ export { default } from "./useThrottle";
@@ -0,0 +1 @@
1
+ export { default } from "./useThrottle";
@@ -0,0 +1,4 @@
1
+ import { DebouncedFunc } from "lodash";
2
+ declare type Callback = (...args: any[]) => void;
3
+ declare const useThrottle: <T extends Callback>(callback: T, delay: number) => DebouncedFunc<T>;
4
+ export default useThrottle;
@@ -0,0 +1,18 @@
1
+ import { useMemo, useEffect, useRef } from "react";
2
+ import throttle from "lodash/throttle";
3
+
4
+ const useThrottle = (callback, delay) => {
5
+ const callbackRef = useRef(callback);
6
+ useEffect(() => {
7
+ callbackRef.current = callback;
8
+ });
9
+ const throttledCallback = useMemo(() => throttle(callbackRef.current, delay), [delay]);
10
+ useEffect(() => {
11
+ return () => {
12
+ throttledCallback.cancel();
13
+ };
14
+ });
15
+ return throttledCallback;
16
+ };
17
+
18
+ export default useThrottle;
@@ -234,6 +234,9 @@ const tabTitleStyles = (0, _styledComponents.css)`
234
234
  text-decoration: none;
235
235
  outline-offset: 0px;
236
236
  margin: 0;
237
+ ${({
238
+ position
239
+ }) => position === "top" && "white-space: nowrap"};
237
240
 
238
241
  a:visited {
239
242
  color: inherit;
@@ -4,10 +4,9 @@ export interface TabHeaderProps {
4
4
  position?: "top" | "left";
5
5
  extendedLine?: boolean;
6
6
  noRightBorder?: boolean;
7
- alternateStyling?: boolean;
8
7
  isInSidebar?: boolean;
9
8
  children: React.ReactNode;
10
9
  align?: "left" | "right";
11
10
  }
12
- declare const TabsHeader: ({ align, children, position, role, extendedLine, alternateStyling, noRightBorder, isInSidebar, }: TabHeaderProps) => JSX.Element;
11
+ declare const TabsHeader: ({ align, children, position, role, extendedLine, noRightBorder, isInSidebar, }: TabHeaderProps) => JSX.Element;
13
12
  export default TabsHeader;
@@ -5,24 +5,64 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _react = _interopRequireDefault(require("react"));
8
+ var _react = _interopRequireWildcard(require("react"));
9
9
 
10
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
11
 
12
12
  var _tabsHeader = require("./tabs-header.style");
13
13
 
14
+ var _useThrottle = _interopRequireDefault(require("../../../../hooks/__internal__/useThrottle"));
15
+
14
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
17
 
18
+ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
19
+
20
+ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
+
22
+ /* In the original prototype the tabs have shadows that fade out as you scroll horizontally.
23
+ * This value is the closest replication to the way that the shadow disappears.
24
+ * It is ultimately tied to the position of the scroll that will then fade the shadow in and out. */
25
+ const fullOpacityThreshold = 128;
26
+
27
+ const getOpacityRatio = value => value / fullOpacityThreshold;
28
+
29
+ const getScrollRight = ({
30
+ scrollWidth,
31
+ clientWidth,
32
+ scrollLeft
33
+ }) => scrollWidth - clientWidth - scrollLeft;
34
+
16
35
  const TabsHeader = ({
17
36
  align = "left",
18
37
  children,
19
38
  position = "top",
20
39
  role,
21
40
  extendedLine,
22
- alternateStyling,
23
41
  noRightBorder = false,
24
42
  isInSidebar = false
25
43
  }) => {
44
+ const [leftScrollOpacity, setLeftScrollOpacity] = (0, _react.useState)(0);
45
+ const [rightScrollOpacity, setRightScrollOpacity] = (0, _react.useState)(1);
46
+ const ref = (0, _react.useRef)(null);
47
+ let isScrollable = false;
48
+ const {
49
+ current
50
+ } = ref;
51
+
52
+ if (position === "top" && current) {
53
+ isScrollable = current.scrollWidth > current.clientWidth;
54
+ }
55
+
56
+ const handleScroll = e => {
57
+ const {
58
+ scrollLeft
59
+ } = e.target;
60
+ const scrollRight = getScrollRight(e.target);
61
+ setLeftScrollOpacity(Math.min(getOpacityRatio(scrollLeft), 1));
62
+ setRightScrollOpacity(Math.min(getOpacityRatio(scrollRight), 1));
63
+ };
64
+
65
+ const throttledHandleScroll = (0, _useThrottle.default)(handleScroll, 50);
26
66
  return /*#__PURE__*/_react.default.createElement(_tabsHeader.StyledTabsHeaderWrapper, {
27
67
  isInSidebar: isInSidebar,
28
68
  position: position
@@ -31,15 +71,18 @@ const TabsHeader = ({
31
71
  position: position,
32
72
  role: role,
33
73
  extendedLine: extendedLine,
34
- alternateStyling: alternateStyling,
35
74
  noRightBorder: noRightBorder,
36
- isInSidebar: isInSidebar
37
- }, children));
75
+ isInSidebar: isInSidebar,
76
+ onScroll: throttledHandleScroll,
77
+ leftScrollOpacity: leftScrollOpacity,
78
+ rightScrollOpacity: rightScrollOpacity,
79
+ isScrollable: isScrollable,
80
+ ref: ref
81
+ }, position === "top" ? /*#__PURE__*/_react.default.createElement(_tabsHeader.StyledTabsWrapper, null, /*#__PURE__*/_react.default.createElement(_tabsHeader.StyledTabsBottomBorderWrapper, null, /*#__PURE__*/_react.default.createElement(_tabsHeader.StyledTabsBottomBorder, null)), children) : children));
38
82
  };
39
83
 
40
84
  TabsHeader.propTypes = {
41
85
  "align": _propTypes.default.oneOf(["left", "right"]),
42
- "alternateStyling": _propTypes.default.bool,
43
86
  "children": _propTypes.default.node,
44
87
  "extendedLine": _propTypes.default.bool,
45
88
  "isInSidebar": _propTypes.default.bool,
@@ -1,6 +1,13 @@
1
1
  import { TabHeaderProps } from "./tabs-header.component";
2
2
  declare type StyledTabsHeaderWrapperProps = Pick<TabHeaderProps, "position" | "isInSidebar">;
3
3
  declare const StyledTabsHeaderWrapper: import("styled-components").StyledComponent<"div", any, StyledTabsHeaderWrapperProps, never>;
4
- export declare type StyledTabsHeaderListProps = Pick<TabHeaderProps, "align" | "alternateStyling" | "extendedLine" | "noRightBorder" | "isInSidebar" | "position">;
4
+ export interface StyledTabsHeaderListProps extends Pick<TabHeaderProps, "align" | "extendedLine" | "noRightBorder" | "isInSidebar" | "position"> {
5
+ leftScrollOpacity?: number;
6
+ rightScrollOpacity?: number;
7
+ isScrollable?: boolean;
8
+ }
5
9
  declare const StyledTabsHeaderList: import("styled-components").StyledComponent<"div", any, StyledTabsHeaderListProps, never>;
6
- export { StyledTabsHeaderWrapper, StyledTabsHeaderList };
10
+ declare const StyledTabsWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
11
+ declare const StyledTabsBottomBorderWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
12
+ declare const StyledTabsBottomBorder: import("styled-components").StyledComponent<"div", any, {}, never>;
13
+ export { StyledTabsHeaderWrapper, StyledTabsHeaderList, StyledTabsWrapper, StyledTabsBottomBorderWrapper, StyledTabsBottomBorder, };
@@ -3,26 +3,19 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.StyledTabsHeaderList = exports.StyledTabsHeaderWrapper = void 0;
6
+ exports.StyledTabsBottomBorder = exports.StyledTabsBottomBorderWrapper = exports.StyledTabsWrapper = exports.StyledTabsHeaderList = exports.StyledTabsHeaderWrapper = void 0;
7
7
 
8
8
  var _styledComponents = _interopRequireWildcard(require("styled-components"));
9
9
 
10
- function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
10
+ var _base = _interopRequireDefault(require("../../../../style/themes/base"));
11
11
 
12
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
13
 
14
- const computeLineWidth = ({
15
- alternateStyling,
16
- isInSidebar,
17
- position
18
- }) => {
19
- if (isInSidebar && position === "left") {
20
- return "0px";
21
- }
14
+ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
22
15
 
23
- return alternateStyling ? "-1px" : "-2px";
24
- };
16
+ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
17
 
18
+ const outlineWidth = "3px";
26
19
  const StyledTabsHeaderWrapper = _styledComponents.default.div`
27
20
  ${({
28
21
  position,
@@ -44,9 +37,21 @@ const StyledTabsHeaderWrapper = _styledComponents.default.div`
44
37
  `}
45
38
  `;
46
39
  exports.StyledTabsHeaderWrapper = StyledTabsHeaderWrapper;
40
+ const commonShadowStyles = (0, _styledComponents.css)`
41
+ pointer-events: none;
42
+ content: "";
43
+ background-repeat: no-repeat;
44
+ background-size: 16px 48px;
45
+ background-attachment: scroll;
46
+ z-index: ${({
47
+ theme
48
+ }) => theme.zIndex.overlay};
49
+ position: sticky;
50
+ min-width: 16px;
51
+ transition: opacity 0.1s ease-in-out;
52
+ `;
47
53
  const StyledTabsHeaderList = _styledComponents.default.div`
48
54
  display: flex;
49
- box-shadow: inset 0px ${computeLineWidth} 0px 0px var(--colorsActionMinor100);
50
55
  ${({
51
56
  extendedLine = true
52
57
  }) => !extendedLine && (0, _styledComponents.css)`
@@ -54,8 +59,57 @@ const StyledTabsHeaderList = _styledComponents.default.div`
54
59
  `}
55
60
  cursor: default;
56
61
  list-style: none;
57
- margin: 0;
58
- padding: 0;
62
+ margin: -${outlineWidth};
63
+ padding: ${outlineWidth};
64
+ overflow-x: auto;
65
+ position: relative;
66
+ ${({
67
+ position
68
+ }) => position === "top" && "white-space: nowrap"};
69
+
70
+ ${({
71
+ isScrollable,
72
+ leftScrollOpacity,
73
+ rightScrollOpacity
74
+ }) => isScrollable && (0, _styledComponents.css)`
75
+ &:before {
76
+ ${commonShadowStyles}
77
+ background: radial-gradient(
78
+ farthest-side at 0 50%,
79
+ rgba(0, 0, 0, 0.2),
80
+ rgba(0, 0, 0, 0)
81
+ );
82
+ background-position: left calc(50% - 4px);
83
+ left: -${outlineWidth};
84
+ margin-right: -16px;
85
+ opacity: ${leftScrollOpacity};
86
+ }
87
+
88
+ &:after {
89
+ ${commonShadowStyles}
90
+ background: radial-gradient(
91
+ farthest-side at 100% 50%,
92
+ rgba(0, 0, 0, 0.2),
93
+ rgba(0, 0, 0, 0)
94
+ );
95
+ background-position: right calc(50% - 4px);
96
+ right: -${outlineWidth};
97
+ margin-left: -16px;
98
+ opacity: ${rightScrollOpacity};
99
+ }
100
+ `}
101
+
102
+ &::-webkit-scrollbar {
103
+ -webkit-appearance: none;
104
+ background: var(--colorsUtilityMajor025);
105
+ height: 8px;
106
+ width: 8px;
107
+ }
108
+
109
+ &::-webkit-scrollbar-thumb {
110
+ background-color: var(--colorsUtilityMajor300);
111
+ cursor: pointer;
112
+ }
59
113
 
60
114
  ${({
61
115
  align = "left"
@@ -81,4 +135,30 @@ const StyledTabsHeaderList = _styledComponents.default.div`
81
135
  `}
82
136
  `}
83
137
  `;
84
- exports.StyledTabsHeaderList = StyledTabsHeaderList;
138
+ exports.StyledTabsHeaderList = StyledTabsHeaderList;
139
+ StyledTabsHeaderList.defaultProps = {
140
+ theme: _base.default
141
+ };
142
+ const StyledTabsWrapper = _styledComponents.default.div`
143
+ position: relative;
144
+ min-width: max-content;
145
+ width: 100%;
146
+ height: 100%;
147
+ `;
148
+ exports.StyledTabsWrapper = StyledTabsWrapper;
149
+ const StyledTabsBottomBorderWrapper = _styledComponents.default.div`
150
+ position: absolute;
151
+ width: 100%;
152
+ height: auto;
153
+ bottom: 0;
154
+ `;
155
+ exports.StyledTabsBottomBorderWrapper = StyledTabsBottomBorderWrapper;
156
+ const StyledTabsBottomBorder = _styledComponents.default.div`
157
+ position: sticky;
158
+ bottom: 2px;
159
+ left: ${outlineWidth};
160
+ right: ${outlineWidth};
161
+ height: 2px;
162
+ background-color: var(--colorsActionMinor100);
163
+ `;
164
+ exports.StyledTabsBottomBorder = StyledTabsBottomBorder;
@@ -72,7 +72,6 @@ const Tabs = ({
72
72
  }).map(() => /*#__PURE__*/(0, _react.createRef)()), [filteredChildren.length]);
73
73
  const previousSelectedTabId = (0, _react.useRef)(selectedTabId);
74
74
  const [selectedTabIdState, setSelectedTabIdState] = (0, _react.useState)(selectedTabId || filteredChildren[0].props.tabId);
75
- const [tabStopId, setTabStopId] = (0, _react.useState)();
76
75
  const {
77
76
  isInSidebar
78
77
  } = (0, _react.useContext)(_drawer.DrawerSidebarContext);
@@ -97,7 +96,6 @@ const Tabs = ({
97
96
  /** Returns true/false for if the given tab id is selected. */
98
97
 
99
98
  const isTabSelected = (0, _react.useCallback)(tabId => tabId === selectedTabIdState, [selectedTabIdState]);
100
- const hasTabStop = (0, _react.useCallback)(tabId => tabId === tabStopId, [tabStopId]);
101
99
  /** Updates the currently visible tab */
102
100
 
103
101
  const updateVisibleTab = (0, _react.useCallback)(tabid => {
@@ -105,14 +103,10 @@ const Tabs = ({
105
103
  setSelectedTabIdState(tabid);
106
104
  }
107
105
 
108
- if (!hasTabStop(tabid)) {
109
- setTabStopId(tabid);
110
- }
111
-
112
106
  if (onTabChange) {
113
107
  onTabChange(tabid);
114
108
  }
115
- }, [onTabChange, isTabSelected, hasTabStop]);
109
+ }, [onTabChange, isTabSelected]);
116
110
  const blurPreviousSelectedTab = (0, _react.useCallback)(() => {
117
111
  const {
118
112
  current
@@ -172,9 +166,7 @@ const Tabs = ({
172
166
  newIndex = 0;
173
167
  }
174
168
 
175
- const nextTabId = tabIds[newIndex];
176
169
  const nextRef = tabRefs[newIndex];
177
- updateVisibleTab(nextTabId);
178
170
  focusTab(nextRef);
179
171
  };
180
172
  /** Handles the keyboard navigation of tabs */
@@ -254,7 +246,7 @@ const Tabs = ({
254
246
  onClick: handleTabClick,
255
247
  onKeyDown: handleKeyDown(index),
256
248
  ref: tabRefs[index],
257
- tabIndex: isTabSelected(tabId) || hasTabStop(tabId) ? 0 : -1,
249
+ tabIndex: isTabSelected(tabId) ? 0 : -1,
258
250
  title: title,
259
251
  href: href,
260
252
  isTabSelected: isTabSelected(tabId),
@@ -281,7 +273,6 @@ const Tabs = ({
281
273
  position: isInSidebar ? "left" : position,
282
274
  role: "tablist",
283
275
  extendedLine: extendedLine,
284
- alternateStyling: variant === "alternate" || isInSidebar,
285
276
  noRightBorder: ["no right side", "no sides"].includes(borders),
286
277
  isInSidebar: isInSidebar
287
278
  }, tabTitles);
@@ -0,0 +1 @@
1
+ export { default } from "./useThrottle";
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "default", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _useThrottle.default;
10
+ }
11
+ });
12
+
13
+ var _useThrottle = _interopRequireDefault(require("./useThrottle"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -0,0 +1,6 @@
1
+ {
2
+ "sideEffects": false,
3
+ "module": "../../../../esm/hooks/__internal__/useThrottle/index.js",
4
+ "main": "./index.js",
5
+ "types": "./index.d.ts"
6
+ }
@@ -0,0 +1,4 @@
1
+ import { DebouncedFunc } from "lodash";
2
+ declare type Callback = (...args: any[]) => void;
3
+ declare const useThrottle: <T extends Callback>(callback: T, delay: number) => DebouncedFunc<T>;
4
+ export default useThrottle;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = require("react");
9
+
10
+ var _throttle = _interopRequireDefault(require("lodash/throttle"));
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ const useThrottle = (callback, delay) => {
15
+ const callbackRef = (0, _react.useRef)(callback);
16
+ (0, _react.useEffect)(() => {
17
+ callbackRef.current = callback;
18
+ });
19
+ const throttledCallback = (0, _react.useMemo)(() => (0, _throttle.default)(callbackRef.current, delay), [delay]);
20
+ (0, _react.useEffect)(() => {
21
+ return () => {
22
+ throttledCallback.cancel();
23
+ };
24
+ });
25
+ return throttledCallback;
26
+ };
27
+
28
+ var _default = useThrottle;
29
+ exports.default = _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "117.3.0",
3
+ "version": "117.4.0",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "files": [
6
6
  "lib",