@elliemae/ds-tabs 2.0.0-rc.12 → 2.0.0-rc.13

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 (105) hide show
  1. package/cjs/DSTabs.js +27 -108
  2. package/cjs/DSTabsCTX.js +30 -0
  3. package/cjs/DSTabsDatatestid.js +18 -0
  4. package/cjs/DSTabsTypes.js +2 -0
  5. package/cjs/config/useCrossRef.js +17 -0
  6. package/cjs/config/useTabs.js +51 -0
  7. package/cjs/defaultProps.js +27 -0
  8. package/cjs/{PanelContainer.js → exportsRelated/DSTab.js} +14 -30
  9. package/cjs/index.js +5 -5
  10. package/cjs/parts/carousel/Carousel.js +71 -0
  11. package/cjs/parts/carousel/styles.js +60 -0
  12. package/cjs/parts/carousel/useCarousel.js +91 -0
  13. package/cjs/parts/carousel/useCarouselCallbacks.js +72 -0
  14. package/cjs/parts/tabBar/TabBar.js +160 -0
  15. package/cjs/parts/tabBar/styles.js +199 -0
  16. package/cjs/parts/tabBar/useTabBar.js +98 -0
  17. package/cjs/parts/tabsContent/TabsContent.js +49 -0
  18. package/cjs/parts/tabsContent/styles.js +15 -0
  19. package/cjs/parts/tabsPanel/TabsPanels.js +77 -0
  20. package/cjs/parts/tabsPanel/styles.js +30 -0
  21. package/cjs/propTypes.js +33 -0
  22. package/cjs/utils/constants.js +29 -0
  23. package/cjs/utils/helpers.js +47 -0
  24. package/cjs/utils/hooks/useKeyboardNavigation.js +61 -0
  25. package/cjs/{useResize.js → utils/hooks/useResize.js} +8 -4
  26. package/cjs/utils/hooks/useTabsCallbacks.js +59 -0
  27. package/esm/DSTabs.js +29 -110
  28. package/esm/DSTabsCTX.js +25 -0
  29. package/esm/DSTabsDatatestid.js +14 -0
  30. package/esm/DSTabsTypes.js +1 -0
  31. package/esm/config/useCrossRef.js +13 -0
  32. package/esm/config/useTabs.js +47 -0
  33. package/esm/defaultProps.js +23 -0
  34. package/esm/{PanelContainer.js → exportsRelated/DSTab.js} +7 -26
  35. package/esm/index.js +4 -3
  36. package/esm/parts/carousel/Carousel.js +63 -0
  37. package/esm/parts/carousel/styles.js +49 -0
  38. package/esm/parts/carousel/useCarousel.js +87 -0
  39. package/esm/parts/carousel/useCarouselCallbacks.js +68 -0
  40. package/esm/parts/tabBar/TabBar.js +151 -0
  41. package/esm/parts/tabBar/styles.js +185 -0
  42. package/esm/parts/tabBar/useTabBar.js +90 -0
  43. package/esm/parts/tabsContent/TabsContent.js +40 -0
  44. package/esm/parts/tabsContent/styles.js +7 -0
  45. package/esm/parts/tabsPanel/TabsPanels.js +67 -0
  46. package/esm/parts/tabsPanel/styles.js +22 -0
  47. package/esm/propTypes.js +28 -0
  48. package/esm/utils/constants.js +21 -0
  49. package/esm/utils/helpers.js +37 -0
  50. package/esm/utils/hooks/useKeyboardNavigation.js +57 -0
  51. package/esm/{useResize.js → utils/hooks/useResize.js} +9 -5
  52. package/esm/utils/hooks/useTabsCallbacks.js +55 -0
  53. package/package.json +95 -35
  54. package/types/DSTabs.d.ts +6 -165
  55. package/types/DSTabsCTX.d.ts +4 -0
  56. package/types/DSTabsDatatestid.d.ts +12 -0
  57. package/types/DSTabsTypes.d.ts +202 -0
  58. package/types/config/useCrossRef.d.ts +2 -0
  59. package/types/config/useTabs.d.ts +2 -0
  60. package/types/defaultProps.d.ts +2 -0
  61. package/types/exportsRelated/DSTab.d.ts +14 -0
  62. package/types/index.d.ts +4 -3
  63. package/types/parts/carousel/Carousel.d.ts +3 -0
  64. package/types/parts/carousel/styles.d.ts +9 -0
  65. package/types/parts/carousel/useCarousel.d.ts +2 -0
  66. package/types/parts/carousel/useCarouselCallbacks.d.ts +2 -0
  67. package/types/parts/tabBar/TabBar.d.ts +2 -0
  68. package/types/parts/tabBar/styles.d.ts +7 -0
  69. package/types/parts/tabBar/useTabBar.d.ts +2 -0
  70. package/types/parts/tabsContent/TabsContent.d.ts +2 -0
  71. package/types/parts/tabsContent/styles.d.ts +1 -0
  72. package/types/parts/tabsPanel/TabsPanels.d.ts +2 -0
  73. package/types/parts/tabsPanel/styles.d.ts +2 -0
  74. package/types/propTypes.d.ts +54 -0
  75. package/types/tests/{DSTabs.events.test.d.ts → DSTabs.callbacks.test.d.ts} +0 -0
  76. package/types/tests/DSTabs.func.test.d.ts +1 -0
  77. package/types/tests/DSTabs.keyboard.test.d.ts +1 -0
  78. package/types/utils/constants.d.ts +19 -0
  79. package/types/utils/helpers.d.ts +8 -0
  80. package/types/utils/hooks/useKeyboardNavigation.d.ts +2 -0
  81. package/types/utils/hooks/useResize.d.ts +2 -0
  82. package/types/utils/hooks/useTabsCallbacks.d.ts +2 -0
  83. package/cjs/Carousel.js +0 -205
  84. package/cjs/DSTab.js +0 -46
  85. package/cjs/SubTabBar.js +0 -54
  86. package/cjs/TabBar.js +0 -417
  87. package/cjs/TabTypes.js +0 -15
  88. package/cjs/TabsImpl.js +0 -120
  89. package/cjs/TabsPanels.js +0 -82
  90. package/esm/Carousel.js +0 -196
  91. package/esm/DSTab.js +0 -36
  92. package/esm/SubTabBar.js +0 -48
  93. package/esm/TabBar.js +0 -407
  94. package/esm/TabTypes.js +0 -10
  95. package/esm/TabsImpl.js +0 -113
  96. package/esm/TabsPanels.js +0 -73
  97. package/types/Carousel.d.ts +0 -16
  98. package/types/DSTab.d.ts +0 -51
  99. package/types/PanelContainer.d.ts +0 -20
  100. package/types/SubTabBar.d.ts +0 -23
  101. package/types/TabBar.d.ts +0 -30
  102. package/types/TabTypes.d.ts +0 -5
  103. package/types/TabsImpl.d.ts +0 -37
  104. package/types/TabsPanels.d.ts +0 -5
  105. package/types/useResize.d.ts +0 -1
package/esm/Carousel.js DELETED
@@ -1,196 +0,0 @@
1
- import _jsx from '@babel/runtime/helpers/esm/jsx';
2
- import 'core-js/modules/web.dom-collections.iterator.js';
3
- import 'core-js/modules/esnext.async-iterator.reduce.js';
4
- import 'core-js/modules/esnext.iterator.constructor.js';
5
- import 'core-js/modules/esnext.iterator.reduce.js';
6
- import 'core-js/modules/esnext.async-iterator.map.js';
7
- import 'core-js/modules/esnext.iterator.map.js';
8
- import React, { useRef, useState, useEffect } from 'react';
9
- import { ChevronLeft, ChevronRight } from '@elliemae/ds-icons';
10
- import styled from 'styled-components';
11
- import DSButton from '@elliemae/ds-button';
12
- import { useResize } from './useResize.js';
13
- import { jsx } from 'react/jsx-runtime';
14
-
15
- const CarouselBtn = /*#__PURE__*/styled(DSButton).withConfig({
16
- componentId: "sc-1317h31-0"
17
- })(["position:absolute;z-index:1;margin:0;&:focus{& span{background-color:", ";background-size:90%;border-radius:2px;border-color:transparent;}}&&{width:16px;height:calc(100% - 2px);@media (min-width:", "){height:calc(100% - 4px);&:focus{& span{background-color:unset;}}}}", " && .em-ds-icon{height:16px;width:16px;}"], props => props.theme.colors.brand[200], _ref => {
18
- let {
19
- theme
20
- } = _ref;
21
- return theme.breakpoints.medium;
22
- }, props => props.right ? 'right: 0;' : 'left: 0;');
23
- const CarouselWrapper = /*#__PURE__*/styled.span.withConfig({
24
- componentId: "sc-1317h31-1"
25
- })(["position:relative;padding:0 16px;width:100%;"]);
26
- const ChildrenWrap = /*#__PURE__*/styled.div.withConfig({
27
- componentId: "sc-1317h31-2"
28
- })(["display:flex;flex-wrap:nowrap;flex:1;overflow:hidden;"]);
29
-
30
- function isVisibleElement(el, container) {
31
- const rect = el.getBoundingClientRect();
32
- const cRect = container.getBoundingClientRect();
33
- const elemLeft = rect.left + 3;
34
- const elemRight = rect.right - 3; // Only completely visible elements return true:
35
-
36
- const isVisible = elemLeft >= cRect.left && elemRight <= cRect.right;
37
- return isVisible;
38
- }
39
-
40
- const Carousel = _ref2 => {
41
- let {
42
- children,
43
- onScroll
44
- } = _ref2;
45
- const itemsRef = useRef([]);
46
- const wrapRef = useRef(null);
47
- const leftRef = useRef(null);
48
- const rightRef = useRef(null);
49
-
50
- const shouldShowLeft = () => children && children[0] && wrapRef.current && itemsRef.current[0] && !isVisibleElement(itemsRef.current[0], wrapRef.current);
51
-
52
- const shouldShowRight = () => children && children[children.length - 1] && wrapRef.current && itemsRef.current[children.length - 1] && !isVisibleElement(itemsRef.current[children.length - 1], wrapRef.current);
53
-
54
- const [{
55
- right,
56
- left,
57
- CHEVRON_FOCUS_FLAG
58
- }, setShow] = useState({
59
- right: false,
60
- left: false,
61
- CHEVRON_FOCUS_FLAG: false // flag to replace lack of callback in useState hook
62
-
63
- });
64
-
65
- const recalcChevrons = () => setShow({
66
- right: shouldShowRight(),
67
- left: shouldShowLeft()
68
- });
69
-
70
- useEffect(() => {
71
- recalcChevrons();
72
- }, []);
73
- useEffect(() => {
74
- if (CHEVRON_FOCUS_FLAG) {
75
- // focus opposite chevron when current one hides
76
- if (!left && right && rightRef.current) {
77
- rightRef.current.focus();
78
- } else if (!right && left && leftRef.current) {
79
- leftRef.current.focus();
80
- }
81
-
82
- setShow({
83
- right,
84
- left,
85
- CHEVRON_FOCUS_FLAG: false
86
- });
87
- }
88
- }, [CHEVRON_FOCUS_FLAG]);
89
- useResize(wrapRef, recalcChevrons);
90
-
91
- const getVisibleItemsOffset = () => itemsRef.current.reduce((acc, c) => {
92
- if (isVisibleElement(c, wrapRef.current)) {
93
- const styles = window.getComputedStyle(c);
94
- const width = c.offsetWidth;
95
- const margin = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
96
- return acc + (width + margin);
97
- }
98
-
99
- return acc;
100
- }, 0);
101
-
102
- const rightClick = () => {
103
- wrapRef.current.scrollLeft += getVisibleItemsOffset();
104
- };
105
-
106
- const leftClick = () => {
107
- wrapRef.current.scrollLeft -= getVisibleItemsOffset();
108
- };
109
-
110
- const handleScroll = e => {
111
- // forces render when element.scrollTop is changed (out of react flow)
112
- setShow({
113
- right: shouldShowRight(),
114
- left: shouldShowLeft(),
115
- // to trigger focus logic at effect above
116
- CHEVRON_FOCUS_FLAG: true
117
- });
118
- onScroll(e);
119
- };
120
-
121
- const handleClick = function (e) {
122
- let onClick = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : () => {};
123
- const tabListDomEl = wrapRef.current;
124
- const el = e.target;
125
- const rect = el.getBoundingClientRect();
126
- const cRect = tabListDomEl.getBoundingClientRect();
127
-
128
- if (!isVisibleElement(el, tabListDomEl)) {
129
- const containerWidth = cRect.width;
130
- const halfContainer = containerWidth / 2;
131
- const elementScrollPosition = rect.left - cRect.left;
132
- const positionInContainer = elementScrollPosition % containerWidth;
133
- const width = el.offsetWidth; // align to right
134
-
135
- if (positionInContainer > halfContainer) {
136
- wrapRef.current.scrollLeft += width + positionInContainer - containerWidth;
137
- } else {
138
- // align left
139
- wrapRef.current.scrollLeft += positionInContainer;
140
- }
141
-
142
- recalcChevrons();
143
- }
144
-
145
- onClick(e);
146
- };
147
-
148
- return /*#__PURE__*/_jsx(CarouselWrapper, {}, void 0, left && /*#__PURE__*/_jsx(CarouselBtn, {
149
- "data-testid": "chevron-left",
150
- buttonType: "link",
151
- innerRef: leftRef,
152
- size: "s",
153
- icon: /*#__PURE__*/_jsx(ChevronLeft, {
154
- size: "s",
155
- color: ['brand-primary', '600']
156
- }),
157
- onClick: leftClick,
158
- tabIndex: -1
159
- }), right && /*#__PURE__*/_jsx(CarouselBtn, {
160
- "data-testid": "chevron-right",
161
- innerRef: rightRef,
162
- right: true,
163
- size: "s",
164
- buttonType: "link",
165
- icon: /*#__PURE__*/_jsx(ChevronRight, {
166
- size: "s",
167
- color: ['brand-primary', '600']
168
- }),
169
- onClick: rightClick,
170
- tabIndex: -1
171
- }), /*#__PURE__*/jsx(ChildrenWrap, {
172
- onScroll: handleScroll,
173
- ref: wrapRef,
174
- children: React.Children.map(children, (child, idx) => /*#__PURE__*/React.cloneElement(child, {
175
- onClick: e => {
176
- var _child$props;
177
-
178
- return handleClick(e, (_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.onClick);
179
- },
180
- key: 'carousel'.concat(idx),
181
- ref: el => {
182
- itemsRef.current[idx] = el; // keep old refs
183
-
184
- if (typeof child.ref === 'function') {
185
- child.ref(el);
186
- }
187
- }
188
- }))
189
- }));
190
- };
191
-
192
- Carousel.defaultProps = {
193
- onScroll: () => null
194
- };
195
-
196
- export { Carousel as default };
package/esm/DSTab.js DELETED
@@ -1,36 +0,0 @@
1
- import _jsx from '@babel/runtime/helpers/esm/jsx';
2
- import 'react';
3
- import { PropTypes, describe } from 'react-desc';
4
-
5
- const DSTab = _ref => {
6
- let {
7
- tabId = '',
8
- title = '',
9
- required = false
10
- } = _ref;
11
- return /*#__PURE__*/_jsx("div", {
12
- "aria-labelledby": "".concat(tabId, "-label"),
13
- tabId: tabId,
14
- title: title,
15
- required: required
16
- });
17
- };
18
-
19
- DSTab.displayName = 'DSTab';
20
- const props = {
21
- /** unique id for tab */
22
- tabId: PropTypes.string.description('unique id for tab'),
23
-
24
- /** tab title */
25
- title: PropTypes.string.description('tab title'),
26
-
27
- /** Show a required mark next to the title */
28
- required: PropTypes.bool.description('Show a required mark next to the title'),
29
-
30
- /** Whether or not it's a ds-tab from DSMobile tabs */
31
- isDSMobile: PropTypes.bool.description("Whether or not it's a ds-tab from DSMobile tabs")
32
- };
33
- const DSTabWithSchema = describe(DSTab);
34
- DSTabWithSchema.propTypes = props;
35
-
36
- export { DSTab, DSTabWithSchema, DSTab as default };
package/esm/SubTabBar.js DELETED
@@ -1,48 +0,0 @@
1
- import _jsx from '@babel/runtime/helpers/esm/jsx';
2
- import 'react';
3
- import { aggregatedClasses } from '@elliemae/ds-classnames';
4
- import TabBar from './TabBar.js';
5
- import Carousel from './Carousel.js';
6
-
7
- const blockName = 'tabs-tab-bar';
8
- const SubTabList = aggregatedClasses('div')(blockName, 'subtabs-list', _ref => {
9
- let {
10
- withCarousel
11
- } = _ref;
12
- return {
13
- carousel: withCarousel
14
- };
15
- });
16
-
17
- const SubTabBar = _ref2 => {
18
- let {
19
- withCarousel,
20
- tabs = [],
21
- activeTab = '',
22
- onTabClick = () => null,
23
- firstSubtabRef,
24
- handleUpArrow
25
- } = _ref2;
26
- return /*#__PURE__*/_jsx(TabBar, {
27
- activeTab: activeTab,
28
- onTabClick: onTabClick,
29
- handleUpArrow: handleUpArrow,
30
- firstSubtabRef: firstSubtabRef,
31
- renderCustomTabBar: _ref3 => {
32
- let {
33
- tabsComponents,
34
- innerRef
35
- } = _ref3;
36
- return /*#__PURE__*/_jsx(SubTabList, {
37
- withCarousel: withCarousel,
38
- innerRef: innerRef,
39
- "data-testid": "subtabs-list"
40
- }, void 0, withCarousel ? /*#__PURE__*/_jsx(Carousel, {}, void 0, tabsComponents) : tabsComponents);
41
- },
42
- showSelectionIndicator: false,
43
- showSeparator: true,
44
- tabs: tabs
45
- });
46
- };
47
-
48
- export { SubTabBar as default };
package/esm/TabBar.js DELETED
@@ -1,407 +0,0 @@
1
- import _jsx from '@babel/runtime/helpers/esm/jsx';
2
- import 'core-js/modules/esnext.async-iterator.map.js';
3
- import 'core-js/modules/esnext.iterator.map.js';
4
- import React, { Component } from 'react';
5
- import { debounce } from 'lodash';
6
- import { aggregatedClasses } from '@elliemae/ds-classnames';
7
- import RequiredMark from '@elliemae/ds-form/RequiredMark';
8
- import memoizeOne from 'memoize-one';
9
- import { ResizeObserver } from 'resize-observer';
10
- import styled from 'styled-components';
11
- import Carousel from './Carousel.js';
12
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
13
-
14
- const blockName = 'tabs-tab-bar';
15
- const gradientWidth = 24;
16
- const StyledTabWrapper = /*#__PURE__*/styled.div.withConfig({
17
- componentId: "sc-7sdovg-0"
18
- })(["display:flex;flex:1;flex-wrap:nowrap;", ";"], _ref => {
19
- let {
20
- flexibleTabsHeaders
21
- } = _ref;
22
- return flexibleTabsHeaders ? '' : 'overflow-x: hidden';
23
- });
24
- const StyledTabList = aggregatedClasses('div')(blockName, 'list', _ref2 => {
25
- let {
26
- withCarousel,
27
- flexibleTabsHeaders,
28
- fixedTabsHeaders,
29
- isDSMobile,
30
- withLeftGradients,
31
- withRightGradients
32
- } = _ref2;
33
- return {
34
- carousel: withCarousel,
35
- 'flexible-table-headers': isDSMobile && flexibleTabsHeaders,
36
- 'fixed-table-headers': isDSMobile && fixedTabsHeaders,
37
- 'left-gradients': isDSMobile && flexibleTabsHeaders && withLeftGradients,
38
- 'right-gradients': isDSMobile && flexibleTabsHeaders && withRightGradients
39
- };
40
- }, {
41
- propsToRemoveFromFinalElement: ['withCarousel', 'flexibleTabsHeaders', 'fixedTabsHeaders', 'withLeftGradients', 'withRightGradients', 'isDSMobile']
42
- });
43
- const TabContainer = aggregatedClasses('button', {
44
- role: 'tab'
45
- })(blockName, 'tab', _ref3 => {
46
- let {
47
- isActive,
48
- showSeparator,
49
- disabled
50
- } = _ref3;
51
- return {
52
- active: isActive,
53
- separator: showSeparator,
54
- disabled
55
- };
56
- });
57
- const SelectionIndicator = aggregatedClasses('div')(blockName, 'selection-indicator');
58
-
59
- class TabBar extends Component {
60
- constructor(_props) {
61
- super(_props);
62
-
63
- this.handleTabClick = (tabId, e) => {
64
- const {
65
- tabListRef,
66
- props
67
- } = this;
68
- const {
69
- onTabClick,
70
- flexibleTabsHeaders,
71
- isDSMobile
72
- } = props;
73
-
74
- if (isDSMobile && flexibleTabsHeaders) {
75
- const tabListDomEl = tabListRef.current;
76
- const el = e.target;
77
- const {
78
- offsetLeft
79
- } = el;
80
- const {
81
- width: elWidth
82
- } = el.getBoundingClientRect();
83
- const {
84
- width: listWidth
85
- } = tabListDomEl.getBoundingClientRect();
86
- const extraSideSpace = listWidth - elWidth;
87
- const leftOffsetToCenter = extraSideSpace > 0 ? extraSideSpace / 2 : 0;
88
- const centeredLeftOffset = offsetLeft > leftOffsetToCenter ? offsetLeft - leftOffsetToCenter : 0;
89
- tabListDomEl.scrollTo({
90
- top: 0,
91
- left: centeredLeftOffset,
92
- behavior: 'smooth'
93
- });
94
- }
95
-
96
- e.preventDefault();
97
- onTabClick(tabId);
98
- };
99
-
100
- this.handleKeyPress = (tabId, e, index) => {
101
- const {
102
- tabs,
103
- handleDownArrow,
104
- handleUpArrow // onTabClick,
105
-
106
- } = this.props;
107
-
108
- if (e.keyCode === 39) {
109
- var _this$tabsRef;
110
-
111
- const nextTab = tabs[index + 1];
112
- if (!nextTab && handleDownArrow) handleDownArrow(e);
113
- if (!nextTab) return; // const { props } = nextTab
114
- // onTabClick(props.tabId)
115
-
116
- (_this$tabsRef = this.tabsRef[index + 1]) === null || _this$tabsRef === void 0 ? void 0 : _this$tabsRef.focus();
117
- }
118
-
119
- if (e.keyCode === 37) {
120
- var _this$tabsRef2;
121
-
122
- const nextTab = tabs[index - 1];
123
- if (!nextTab && handleUpArrow) handleUpArrow(e);
124
- if (!nextTab) return; // const { props } = nextTab
125
- // onTabClick(props.tabId)
126
-
127
- (_this$tabsRef2 = this.tabsRef[index - 1]) === null || _this$tabsRef2 === void 0 ? void 0 : _this$tabsRef2.focus();
128
- }
129
-
130
- if (e.keyCode === 40 && handleDownArrow) {
131
- handleDownArrow(e);
132
- }
133
-
134
- if (e.keyCode === 38 && handleUpArrow) {
135
- handleUpArrow(e);
136
- }
137
- };
138
-
139
- this.handleTabsHeadersHorizontalScroll = debounce(() => {
140
- const {
141
- tabListRef,
142
- props
143
- } = this;
144
- const {
145
- flexibleTabsHeaders,
146
- isDSMobile
147
- } = props;
148
-
149
- if (isDSMobile && flexibleTabsHeaders) {
150
- const tabListDomEl = tabListRef.current;
151
- const {
152
- scrollLeft,
153
- scrollWidth,
154
- clientWidth
155
- } = tabListDomEl;
156
- const withLeftGradients = this.shouldHaveLeftGradient(scrollLeft, gradientWidth);
157
- const withRightGradients = this.shouldHaveRightGradient(scrollLeft, gradientWidth, clientWidth, scrollWidth);
158
- this.setState({
159
- withLeftGradients,
160
- withRightGradients
161
- });
162
- }
163
- }, 50);
164
- this.renderTabs = memoizeOne((activeTab, tabs) => {
165
- const {
166
- showSeparator
167
- } = this.props;
168
- return React.Children.map(tabs, (tab, index) => {
169
- const {
170
- tabId,
171
- title,
172
- style,
173
- required,
174
- disabled
175
- } = tab.props;
176
- const isActive = activeTab === tabId;
177
- return [/*#__PURE__*/jsxs(TabContainer, {
178
- // eslint-disable-next-line no-return-assign
179
- ref: t => {
180
- this.tabsRef[index] = t;
181
-
182
- if (index === 0 && this.props.firstSubtabRef) {
183
- this.props.firstSubtabRef.current = t;
184
- }
185
-
186
- if (index === tabs.length - 1 && this.props.lastTabRef) {
187
- this.props.lastTabRef.current = t;
188
- }
189
- },
190
- "aria-controls": tabId,
191
- "aria-selected": isActive,
192
- "aria-disabled": !!disabled,
193
- classProps: {
194
- isActive,
195
- showSeparator,
196
- disabled
197
- },
198
- "data-tab-id": tabId,
199
- id: "".concat(tabId, "-label"),
200
- onClick: e => {
201
- if (!disabled) this.handleTabClick(tabId, e, index);
202
- },
203
- onKeyDown: e => {
204
- if (!disabled) this.handleKeyPress(tabId, e, index);
205
- },
206
- style: style,
207
- tabIndex: 0,
208
- children: [title, /*#__PURE__*/_jsx(RequiredMark, {
209
- required: required
210
- })]
211
- }, tabId)];
212
- }, null);
213
- });
214
- this.tabListRef = /*#__PURE__*/React.createRef();
215
- this.resizeObserver = new ResizeObserver(() => this.setIndicatorStyle());
216
- this.state = {
217
- indicatorStyle: null,
218
- withLeftGradients: false,
219
- withRightGradients: false
220
- };
221
- this.setIndicatorStyle = this.setIndicatorStyle.bind(this);
222
- this.getIndicatorStyles = this.getIndicatorStyles.bind(this);
223
- this.handleGradients = this.handleGradients.bind(this);
224
- this.handleTabsHeadersHorizontalScroll = this.handleTabsHeadersHorizontalScroll.bind(this);
225
- this.tabsRef = {};
226
- this.setIndicatorStyle = this.setIndicatorStyle.bind(this);
227
- }
228
-
229
- componentDidMount() {
230
- const {
231
- showSelectionIndicator
232
- } = this.props;
233
- this.resizeObserver.observe(this.tabListRef.current);
234
-
235
- if (showSelectionIndicator) {
236
- this.setIndicatorStyle();
237
- }
238
-
239
- window.addEventListener('resize', this.handleGradients);
240
- window.addEventListener('orientationchange', this.handleGradients);
241
- this.handleGradients();
242
- }
243
-
244
- componentDidUpdate(prevProps) {
245
- const {
246
- activeTab,
247
- showSelectionIndicator
248
- } = this.props;
249
-
250
- if (showSelectionIndicator && prevProps.activeTab !== activeTab) {
251
- this.setIndicatorStyle(activeTab);
252
- }
253
- }
254
-
255
- componentWillUnmount() {
256
- this.resizeObserver.unobserve(this.tabListRef.current);
257
- window.removeEventListener('resize', this.handleGradients);
258
- window.removeEventListener('orientationchange', this.handleGradients);
259
- }
260
-
261
- handleGradients() {
262
- const {
263
- scrollLeft,
264
- scrollWidth,
265
- clientWidth
266
- } = this.tabListRef.current;
267
- const withLeftGradients = this.shouldHaveLeftGradient(scrollLeft, gradientWidth);
268
- const withRightGradients = this.shouldHaveRightGradient(scrollLeft, gradientWidth, clientWidth, scrollWidth);
269
- this.setState({
270
- withLeftGradients,
271
- withRightGradients
272
- });
273
- }
274
-
275
- shouldHaveLeftGradient(scrollLeft, gWidth) {
276
- return Math.abs(scrollLeft) > gWidth;
277
- } // eslint-disable-next-line max-params
278
-
279
-
280
- shouldHaveRightGradient(scrollLeft, gWidth, clientWidth, scrollWidth) {
281
- return Math.abs(scrollLeft) <= scrollWidth - (clientWidth + gWidth);
282
- }
283
-
284
- setIndicatorStyle() {
285
- const {
286
- activeTab
287
- } = this.props;
288
- setTimeout(() => this.setState({
289
- indicatorStyle: this.getIndicatorStyles(activeTab)
290
- }), 100);
291
- }
292
-
293
- getActiveTabElement(activeTab) {
294
- const tabListEl = this.tabListRef.current;
295
- const tabSelector = "[data-tab-id=\"".concat(activeTab, "\"]");
296
- return tabListEl && tabListEl.querySelector(tabSelector);
297
- }
298
-
299
- isElementVisible(el, holder) {
300
- const {
301
- left,
302
- right,
303
- width
304
- } = el.getBoundingClientRect();
305
- const holderRect = holder.getBoundingClientRect();
306
- return left <= holderRect.left ? holderRect.left - left <= width : right - holderRect.right <= width;
307
- }
308
-
309
- getVisibleDimensions(node, referenceNode) {
310
- const pos = node.getBoundingClientRect();
311
- const referencePos = referenceNode.getBoundingClientRect();
312
- return {
313
- width: Math.min(node.clientWidth, referencePos.left + referenceNode.clientWidth - pos.left, node.clientWidth - (referencePos.left - pos.left)),
314
- height: Math.min(node.clientHeight, referencePos.top + referenceNode.clientHeight - pos.top, node.clientHeight - (referencePos.top - pos.top))
315
- };
316
- }
317
-
318
- getIndicatorStyles(activeTab) {
319
- const tabListEl = this.tabListRef.current;
320
- const {
321
- withCarousel
322
- } = this.props;
323
- const activeTabEl = this.getActiveTabElement(activeTab);
324
- if (!activeTabEl || !this.isElementVisible(activeTabEl, tabListEl)) return null;
325
- const {
326
- clientHeight,
327
- clientWidth,
328
- offsetTop,
329
- offsetLeft
330
- } = activeTabEl;
331
- const {
332
- left
333
- } = activeTabEl.getBoundingClientRect();
334
- const leftOff = withCarousel ? Math.max(0, left - tabListEl.getBoundingClientRect().left) : offsetLeft;
335
- const width = withCarousel ? this.getVisibleDimensions(activeTabEl, tabListEl).width + 2 : clientWidth + 2;
336
- return {
337
- height: clientHeight,
338
- left: "".concat(Math.floor(leftOff), "px"),
339
- // using left and top for ie compatibility
340
- top: "".concat(Math.floor(offsetTop), "px"),
341
- width
342
- };
343
- }
344
-
345
- render() {
346
- const {
347
- id,
348
- tabs,
349
- activeTab,
350
- renderCustomTabBar,
351
- withCarousel,
352
- isDSMobile,
353
- flexibleTabsHeaders,
354
- fixedTabsHeaders
355
- } = this.props;
356
- const {
357
- indicatorStyle,
358
- withLeftGradients,
359
- withRightGradients
360
- } = this.state;
361
-
362
- if (renderCustomTabBar) {
363
- return renderCustomTabBar({
364
- innerRef: this.tabListRef,
365
- withCarousel,
366
- tabsComponents: this.renderTabs(activeTab, tabs)
367
- });
368
- }
369
-
370
- const shouldUseCarousel = !isDSMobile && withCarousel;
371
- return /*#__PURE__*/jsx(Fragment, {
372
- children: /*#__PURE__*/_jsx(StyledTabList, {
373
- withCarousel: withCarousel,
374
- "aria-label": id,
375
- innerRef: this.tabListRef,
376
- role: "tablist",
377
- "data-testid": "tab-list",
378
- isDSMobile: isDSMobile,
379
- flexibleTabsHeaders: flexibleTabsHeaders,
380
- withLeftGradients: withLeftGradients,
381
- withRightGradients: withRightGradients,
382
- fixedTabsHeaders: fixedTabsHeaders,
383
- onScroll: this.handleTabsHeadersHorizontalScroll,
384
- style: {
385
- width: '100%'
386
- }
387
- }, void 0, /*#__PURE__*/_jsx(StyledTabWrapper, {
388
- isDSMobile: isDSMobile,
389
- flexibleTabsHeaders: flexibleTabsHeaders,
390
- fixedTabsHeaders: fixedTabsHeaders
391
- }, void 0, shouldUseCarousel ? /*#__PURE__*/_jsx(Carousel, {
392
- onScroll: this.setIndicatorStyle
393
- }, void 0, this.renderTabs(activeTab, tabs)) : null, !shouldUseCarousel ? this.renderTabs(activeTab, tabs) : null, /*#__PURE__*/_jsx(SelectionIndicator, {
394
- style: indicatorStyle
395
- })))
396
- });
397
- }
398
-
399
- }
400
-
401
- TabBar.defaultProps = {
402
- showSelectionIndicator: true,
403
- showSeparator: false,
404
- isDSMobile: false
405
- };
406
-
407
- export { TabBar as default };
package/esm/TabTypes.js DELETED
@@ -1,10 +0,0 @@
1
- import 'core-js/modules/esnext.async-iterator.map.js';
2
- import 'core-js/modules/esnext.iterator.map.js';
3
-
4
- const TabTypes = {
5
- NORMAL: 'normal',
6
- SUBTABS: 'subtabs'
7
- };
8
- const getTabTypes = () => Object.keys(TabTypes).map(key => TabTypes[key]);
9
-
10
- export { TabTypes, getTabTypes };