@elliemae/ds-tabs 2.2.1 → 2.2.2-rc.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.
@@ -11,6 +11,7 @@ var useTabBar = require('./useTabBar.js');
11
11
  var styles = require('./styles.js');
12
12
  var DSTabsCTX = require('../../DSTabsCTX.js');
13
13
  var useKeyboardNavigation = require('../../utils/hooks/useKeyboardNavigation.js');
14
+ var helpers = require('../../utils/helpers.js');
14
15
  var constants = require('../../utils/constants.js');
15
16
  var useTabsCallbacks = require('../../utils/hooks/useTabsCallbacks.js');
16
17
  var DSTabsDatatestid = require('../../DSTabsDatatestid.js');
@@ -28,6 +29,7 @@ const TabBar = () => {
28
29
  focusableTabsRef,
29
30
  tabsListRef,
30
31
  tabsRefAsArray,
32
+ carouselOnlyListRef,
31
33
  actualActiveTab,
32
34
  props: {
33
35
  type,
@@ -113,6 +115,12 @@ const TabBar = () => {
113
115
 
114
116
  if (onClick && !disabled) onClick(tabId, e);
115
117
  },
118
+ onFocus: e => {
119
+ if (withCarousel) helpers.centerTab({
120
+ e,
121
+ listRef: carouselOnlyListRef
122
+ });
123
+ },
116
124
  onKeyDown: e => {
117
125
  if (e.key === 'Enter') e.stopPropagation();
118
126
  if (!disabled) handleOnKeyDown(e);
@@ -122,7 +130,7 @@ const TabBar = () => {
122
130
  children: [title, required && (_StyledRequiredMark || (_StyledRequiredMark = /*#__PURE__*/_jsx__default["default"](styles.StyledRequiredMark, {}, void 0, "\u25CF")))]
123
131
  }, tabId);
124
132
  });
125
- }, [tabs, actualActiveTab, isDSMobile, fixedTabsHeaders, type, withCarousel, showSeparator, tabsRefAsArray, focusableTabsRef, tabsRef, firstSubtabInternalRef, lastTabInternalRef, handleOnTabChange, updateIndicatorStyle, handleOnKeyDown]);
133
+ }, [tabs, actualActiveTab, isDSMobile, fixedTabsHeaders, type, withCarousel, showSeparator, tabsRefAsArray, focusableTabsRef, tabsRef, firstSubtabInternalRef, lastTabInternalRef, handleOnTabChange, updateIndicatorStyle, carouselOnlyListRef, handleOnKeyDown]);
126
134
 
127
135
  if (type === constants.TabTypes.SUBTABS && !isDSMobile) {
128
136
  return /*#__PURE__*/jsxRuntime.jsx(styles.StyledSubTabsList, {
@@ -66,15 +66,6 @@ const useTabBar = () => {
66
66
  });
67
67
  }
68
68
  }, [fixedTabsHeaders, isDSMobile, tabsListRef]);
69
- React.useEffect(() => {
70
- if (showSelectionIndicator) {
71
- updateIndicatorStyle();
72
- }
73
-
74
- if (isDSMobile && !fixedTabsHeaders) {
75
- updateMobileGradients();
76
- }
77
- }, [updateIndicatorStyle, showSelectionIndicator, actualActiveTab, updateMobileGradients, isDSMobile, fixedTabsHeaders]);
78
69
  React.useLayoutEffect(() => {
79
70
  if (showSelectionIndicator) {
80
71
  updateIndicatorStyle();
@@ -83,7 +74,7 @@ const useTabBar = () => {
83
74
  if (isDSMobile && !fixedTabsHeaders) {
84
75
  updateMobileGradients();
85
76
  }
86
- }, [updateMobileGradients, showSelectionIndicator, updateIndicatorStyle, isDSMobile, fixedTabsHeaders]);
77
+ }, [updateMobileGradients, showSelectionIndicator, updateIndicatorStyle, isDSMobile, fixedTabsHeaders, actualActiveTab]);
87
78
  return {
88
79
  updateIndicatorStyle,
89
80
  setIndicatorStyle,
@@ -25,6 +25,33 @@ const isElementVisibleCarousel = function (tab, tabContainer) {
25
25
 
26
26
  return false;
27
27
  };
28
+ const centerTab = _ref => {
29
+ let {
30
+ e,
31
+ listRef
32
+ } = _ref;
33
+
34
+ if (listRef.current) {
35
+ const {
36
+ offsetLeft
37
+ } = e === null || e === void 0 ? void 0 : e.target;
38
+ const {
39
+ width: tabWidth
40
+ } = (e === null || e === void 0 ? void 0 : e.target).getBoundingClientRect();
41
+ const {
42
+ width: listWidth
43
+ } = listRef.current.getBoundingClientRect();
44
+ const extraSideSpace = listWidth - tabWidth;
45
+ const leftOffsetToCenter = extraSideSpace > 0 ? extraSideSpace / 2 : 0;
46
+ const centeredLeftOffset = offsetLeft > leftOffsetToCenter ? offsetLeft - leftOffsetToCenter : 0;
47
+ listRef.current.scrollTo({
48
+ top: 0,
49
+ left: centeredLeftOffset,
50
+ behavior: 'smooth'
51
+ });
52
+ e === null || e === void 0 ? void 0 : e.preventDefault();
53
+ }
54
+ };
28
55
  const getVisibleDimensions = (node, referenceNode) => {
29
56
  const nodeDimensions = node.getBoundingClientRect();
30
57
  const referenceNodeDimensions = referenceNode.getBoundingClientRect();
@@ -38,6 +65,7 @@ const getIdByIndex = (children, index) => children && children[index].props.tabI
38
65
  const shouldHaveLeftGradient = scrollLeft => Math.abs(scrollLeft) > constants.MOBILE_GRADIENT_WIDTH;
39
66
  const shouldHaveRightGradient = (scrollLeft, clientWidth, scrollWidth) => Math.abs(scrollLeft) <= scrollWidth - (clientWidth + constants.MOBILE_GRADIENT_WIDTH);
40
67
 
68
+ exports.centerTab = centerTab;
41
69
  exports.getIdByIndex = getIdByIndex;
42
70
  exports.getIndexById = getIndexById;
43
71
  exports.getVisibleDimensions = getVisibleDimensions;
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
+ var helpers = require('../helpers.js');
6
7
  var DSTabsCTX = require('../../DSTabsCTX.js');
7
8
 
8
9
  const useTabsCallbacks = () => {
@@ -16,36 +17,17 @@ const useTabsCallbacks = () => {
16
17
  fixedTabsHeaders
17
18
  }
18
19
  } = React.useContext(DSTabsCTX.DSTabsContext);
19
- const centerTabWhenTabChangeMobile = React.useCallback(e => {
20
- if (tabsListRef.current) {
21
- const {
22
- offsetLeft
23
- } = e === null || e === void 0 ? void 0 : e.target;
24
- const {
25
- width: tabWidth
26
- } = (e === null || e === void 0 ? void 0 : e.target).getBoundingClientRect();
27
- const {
28
- width: listWidth
29
- } = tabsListRef.current.getBoundingClientRect();
30
- const extraSideSpace = listWidth - tabWidth;
31
- const leftOffsetToCenter = extraSideSpace > 0 ? extraSideSpace / 2 : 0;
32
- const centeredLeftOffset = offsetLeft > leftOffsetToCenter ? offsetLeft - leftOffsetToCenter : 0;
33
- tabsListRef.current.scrollTo({
34
- top: 0,
35
- left: centeredLeftOffset,
36
- behavior: 'smooth'
37
- });
38
- e === null || e === void 0 ? void 0 : e.preventDefault();
39
- }
40
- }, [tabsListRef]);
41
20
  const handleOnTabChange = React.useCallback((tabId, e) => {
42
21
  setInternalActiveTab(tabId);
43
22
  onTabChange(tabId, e);
44
23
 
45
24
  if (isDSMobile && !fixedTabsHeaders && e) {
46
- centerTabWhenTabChangeMobile(e);
25
+ helpers.centerTab({
26
+ e,
27
+ listRef: tabsListRef
28
+ });
47
29
  }
48
- }, [centerTabWhenTabChangeMobile, fixedTabsHeaders, isDSMobile, onTabChange, setInternalActiveTab]);
30
+ }, [fixedTabsHeaders, isDSMobile, onTabChange, setInternalActiveTab, tabsListRef]);
49
31
  const handleOnMouseDown = React.useCallback(e => {
50
32
  const role = e.target.getAttribute('role');
51
33
  if (role !== 'tabpanel' && allowTextSelection) e.stopPropagation();
@@ -7,6 +7,7 @@ import { useTabBar } from './useTabBar.js';
7
7
  import { StyledTabButton, StyledRequiredMark, StyledSubTabsList, StyledTabList, StyledTabWrapper, StyledSelectionIndicator } from './styles.js';
8
8
  import { DSTabsContext, DSTabsCrossRefContext } from '../../DSTabsCTX.js';
9
9
  import { useKeyboardNavigation } from '../../utils/hooks/useKeyboardNavigation.js';
10
+ import { centerTab } from '../../utils/helpers.js';
10
11
  import { TabTypes } from '../../utils/constants.js';
11
12
  import { useTabsCallbacks } from '../../utils/hooks/useTabsCallbacks.js';
12
13
  import { DSTabsDatatestid } from '../../DSTabsDatatestid.js';
@@ -19,6 +20,7 @@ const TabBar = () => {
19
20
  focusableTabsRef,
20
21
  tabsListRef,
21
22
  tabsRefAsArray,
23
+ carouselOnlyListRef,
22
24
  actualActiveTab,
23
25
  props: {
24
26
  type,
@@ -104,6 +106,12 @@ const TabBar = () => {
104
106
 
105
107
  if (onClick && !disabled) onClick(tabId, e);
106
108
  },
109
+ onFocus: e => {
110
+ if (withCarousel) centerTab({
111
+ e,
112
+ listRef: carouselOnlyListRef
113
+ });
114
+ },
107
115
  onKeyDown: e => {
108
116
  if (e.key === 'Enter') e.stopPropagation();
109
117
  if (!disabled) handleOnKeyDown(e);
@@ -113,7 +121,7 @@ const TabBar = () => {
113
121
  children: [title, required && (_StyledRequiredMark || (_StyledRequiredMark = /*#__PURE__*/_jsx(StyledRequiredMark, {}, void 0, "\u25CF")))]
114
122
  }, tabId);
115
123
  });
116
- }, [tabs, actualActiveTab, isDSMobile, fixedTabsHeaders, type, withCarousel, showSeparator, tabsRefAsArray, focusableTabsRef, tabsRef, firstSubtabInternalRef, lastTabInternalRef, handleOnTabChange, updateIndicatorStyle, handleOnKeyDown]);
124
+ }, [tabs, actualActiveTab, isDSMobile, fixedTabsHeaders, type, withCarousel, showSeparator, tabsRefAsArray, focusableTabsRef, tabsRef, firstSubtabInternalRef, lastTabInternalRef, handleOnTabChange, updateIndicatorStyle, carouselOnlyListRef, handleOnKeyDown]);
117
125
 
118
126
  if (type === TabTypes.SUBTABS && !isDSMobile) {
119
127
  return /*#__PURE__*/jsx(StyledSubTabsList, {
@@ -1,5 +1,5 @@
1
1
  import 'core-js/modules/web.dom-collections.iterator.js';
2
- import { useContext, useState, useCallback, useEffect, useLayoutEffect } from 'react';
2
+ import { useContext, useState, useCallback, useLayoutEffect } from 'react';
3
3
  import useResizeObserver from '@react-hook/resize-observer';
4
4
  import { isElementVisible, shouldHaveLeftGradient, shouldHaveRightGradient } from '../../utils/helpers.js';
5
5
  import { DSTabsContext } from '../../DSTabsCTX.js';
@@ -58,15 +58,6 @@ const useTabBar = () => {
58
58
  });
59
59
  }
60
60
  }, [fixedTabsHeaders, isDSMobile, tabsListRef]);
61
- useEffect(() => {
62
- if (showSelectionIndicator) {
63
- updateIndicatorStyle();
64
- }
65
-
66
- if (isDSMobile && !fixedTabsHeaders) {
67
- updateMobileGradients();
68
- }
69
- }, [updateIndicatorStyle, showSelectionIndicator, actualActiveTab, updateMobileGradients, isDSMobile, fixedTabsHeaders]);
70
61
  useLayoutEffect(() => {
71
62
  if (showSelectionIndicator) {
72
63
  updateIndicatorStyle();
@@ -75,7 +66,7 @@ const useTabBar = () => {
75
66
  if (isDSMobile && !fixedTabsHeaders) {
76
67
  updateMobileGradients();
77
68
  }
78
- }, [updateMobileGradients, showSelectionIndicator, updateIndicatorStyle, isDSMobile, fixedTabsHeaders]);
69
+ }, [updateMobileGradients, showSelectionIndicator, updateIndicatorStyle, isDSMobile, fixedTabsHeaders, actualActiveTab]);
79
70
  return {
80
71
  updateIndicatorStyle,
81
72
  setIndicatorStyle,
@@ -21,6 +21,33 @@ const isElementVisibleCarousel = function (tab, tabContainer) {
21
21
 
22
22
  return false;
23
23
  };
24
+ const centerTab = _ref => {
25
+ let {
26
+ e,
27
+ listRef
28
+ } = _ref;
29
+
30
+ if (listRef.current) {
31
+ const {
32
+ offsetLeft
33
+ } = e === null || e === void 0 ? void 0 : e.target;
34
+ const {
35
+ width: tabWidth
36
+ } = (e === null || e === void 0 ? void 0 : e.target).getBoundingClientRect();
37
+ const {
38
+ width: listWidth
39
+ } = listRef.current.getBoundingClientRect();
40
+ const extraSideSpace = listWidth - tabWidth;
41
+ const leftOffsetToCenter = extraSideSpace > 0 ? extraSideSpace / 2 : 0;
42
+ const centeredLeftOffset = offsetLeft > leftOffsetToCenter ? offsetLeft - leftOffsetToCenter : 0;
43
+ listRef.current.scrollTo({
44
+ top: 0,
45
+ left: centeredLeftOffset,
46
+ behavior: 'smooth'
47
+ });
48
+ e === null || e === void 0 ? void 0 : e.preventDefault();
49
+ }
50
+ };
24
51
  const getVisibleDimensions = (node, referenceNode) => {
25
52
  const nodeDimensions = node.getBoundingClientRect();
26
53
  const referenceNodeDimensions = referenceNode.getBoundingClientRect();
@@ -34,4 +61,4 @@ const getIdByIndex = (children, index) => children && children[index].props.tabI
34
61
  const shouldHaveLeftGradient = scrollLeft => Math.abs(scrollLeft) > MOBILE_GRADIENT_WIDTH;
35
62
  const shouldHaveRightGradient = (scrollLeft, clientWidth, scrollWidth) => Math.abs(scrollLeft) <= scrollWidth - (clientWidth + MOBILE_GRADIENT_WIDTH);
36
63
 
37
- export { getIdByIndex, getIndexById, getVisibleDimensions, isElementVisible, isElementVisibleCarousel, shouldHaveLeftGradient, shouldHaveRightGradient };
64
+ export { centerTab, getIdByIndex, getIndexById, getVisibleDimensions, isElementVisible, isElementVisibleCarousel, shouldHaveLeftGradient, shouldHaveRightGradient };
@@ -1,4 +1,5 @@
1
1
  import { useContext, useCallback } from 'react';
2
+ import { centerTab } from '../helpers.js';
2
3
  import { DSTabsContext } from '../../DSTabsCTX.js';
3
4
 
4
5
  const useTabsCallbacks = () => {
@@ -12,36 +13,17 @@ const useTabsCallbacks = () => {
12
13
  fixedTabsHeaders
13
14
  }
14
15
  } = useContext(DSTabsContext);
15
- const centerTabWhenTabChangeMobile = useCallback(e => {
16
- if (tabsListRef.current) {
17
- const {
18
- offsetLeft
19
- } = e === null || e === void 0 ? void 0 : e.target;
20
- const {
21
- width: tabWidth
22
- } = (e === null || e === void 0 ? void 0 : e.target).getBoundingClientRect();
23
- const {
24
- width: listWidth
25
- } = tabsListRef.current.getBoundingClientRect();
26
- const extraSideSpace = listWidth - tabWidth;
27
- const leftOffsetToCenter = extraSideSpace > 0 ? extraSideSpace / 2 : 0;
28
- const centeredLeftOffset = offsetLeft > leftOffsetToCenter ? offsetLeft - leftOffsetToCenter : 0;
29
- tabsListRef.current.scrollTo({
30
- top: 0,
31
- left: centeredLeftOffset,
32
- behavior: 'smooth'
33
- });
34
- e === null || e === void 0 ? void 0 : e.preventDefault();
35
- }
36
- }, [tabsListRef]);
37
16
  const handleOnTabChange = useCallback((tabId, e) => {
38
17
  setInternalActiveTab(tabId);
39
18
  onTabChange(tabId, e);
40
19
 
41
20
  if (isDSMobile && !fixedTabsHeaders && e) {
42
- centerTabWhenTabChangeMobile(e);
21
+ centerTab({
22
+ e,
23
+ listRef: tabsListRef
24
+ });
43
25
  }
44
- }, [centerTabWhenTabChangeMobile, fixedTabsHeaders, isDSMobile, onTabChange, setInternalActiveTab]);
26
+ }, [fixedTabsHeaders, isDSMobile, onTabChange, setInternalActiveTab, tabsListRef]);
45
27
  const handleOnMouseDown = useCallback(e => {
46
28
  const role = e.target.getAttribute('role');
47
29
  if (role !== 'tabpanel' && allowTextSelection) e.stopPropagation();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elliemae/ds-tabs",
3
- "version": "2.2.1",
3
+ "version": "2.2.2-rc.0",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - Tabs",
6
6
  "module": "./esm/index.js",
@@ -128,11 +128,11 @@
128
128
  "build": "node ../../scripts/build/build.js"
129
129
  },
130
130
  "dependencies": {
131
- "@elliemae/ds-button": "2.2.1",
132
- "@elliemae/ds-icon": "2.2.1",
133
- "@elliemae/ds-icons": "2.2.1",
134
- "@elliemae/ds-props-helpers": "2.2.1",
135
- "@elliemae/ds-system": "2.2.1",
131
+ "@elliemae/ds-button": "2.2.2-rc.0",
132
+ "@elliemae/ds-icon": "2.2.2-rc.0",
133
+ "@elliemae/ds-icons": "2.2.2-rc.0",
134
+ "@elliemae/ds-props-helpers": "2.2.2-rc.0",
135
+ "@elliemae/ds-system": "2.2.2-rc.0",
136
136
  "@react-hook/resize-observer": "~1.2.5",
137
137
  "prop-types": "~15.7.2",
138
138
  "react-desc": "~4.1.3",
@@ -162,6 +162,10 @@ export interface VisibleDimensionsT {
162
162
  width: number;
163
163
  height: number;
164
164
  }
165
+ export interface CenterTabPropsT {
166
+ e?: React.MouseEvent | React.FocusEvent;
167
+ listRef: React.MutableRefObject<HTMLDivElement | null>;
168
+ }
165
169
  export interface StyledTabWrapperPropsT {
166
170
  isDSMobile: boolean;
167
171
  fixedTabsHeaders: boolean;
@@ -1,6 +1,7 @@
1
- import type { DSTabPropsWithDefaultT, VisibleDimensionsT } from '../DSTabsTypes';
1
+ import type { CenterTabPropsT, DSTabPropsWithDefaultT, VisibleDimensionsT } from '../DSTabsTypes';
2
2
  export declare const isElementVisible: (tab: HTMLElement, tabList: HTMLElement) => boolean;
3
3
  export declare const isElementVisibleCarousel: (tab: HTMLElement | null, tabContainer: HTMLDivElement | null, firstOrLastItem?: boolean) => boolean;
4
+ export declare const centerTab: ({ e, listRef }: CenterTabPropsT) => void;
4
5
  export declare const getVisibleDimensions: (node: HTMLElement, referenceNode: HTMLElement) => VisibleDimensionsT;
5
6
  export declare const getIndexById: (children: React.ReactElement<DSTabPropsWithDefaultT>[], activeId?: string | undefined) => number;
6
7
  export declare const getIdByIndex: (children: React.ReactElement<DSTabPropsWithDefaultT>[], index: number) => string;