Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 13 additions & 25 deletions src/components/Tab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@ import React, { useEffect, useRef } from 'react';
import cx from 'clsx';

const DEFAULT_CLASS = 'react-tabs__tab';
const defaultProps = {
className: DEFAULT_CLASS,
disabledClassName: `${DEFAULT_CLASS}--disabled`,
focus: false,
id: null,
selected: false,
selectedClassName: `${DEFAULT_CLASS}--selected`,
};

/*
Left for TS migration
Expand All @@ -34,24 +26,20 @@ const propTypes = {
tabRef: PropTypes.func, // private
};*/

const Tab = (props) => {
const Tab = ({
children,
className = DEFAULT_CLASS,
disabled,
disabledClassName = `${DEFAULT_CLASS}--disabled`,
focus = false,
id = null,
selected = false,
selectedClassName = `${DEFAULT_CLASS}--selected`,
tabIndex,
tabRef,
...attributes
}) => {
let nodeRef = useRef();
const {
children,
className,
disabled,
disabledClassName,
focus,
id,
selected,
selectedClassName,
tabIndex,
tabRef,
...attributes
} = {
...defaultProps,
...props,
};

useEffect(() => {
if (selected && focus) {
Expand Down
14 changes: 5 additions & 9 deletions src/components/TabList.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import React from 'react';
import cx from 'clsx';

const defaultProps = {
className: 'react-tabs__tab-list',
};

/*
Left for TS migration
const propTypes = {
Expand All @@ -15,12 +11,12 @@ const propTypes = {
PropTypes.object,
]),
};*/
const TabList = (props) => {
const { children, className, ...attributes } = {
...defaultProps,
...props,
};

const TabList = ({
children,
className = 'react-tabs__tab-list',
...attributes
}) => {
return (
<ul {...attributes} className={cx(className)} role="tablist">
{children}
Expand Down
27 changes: 9 additions & 18 deletions src/components/TabPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import React from 'react';
import cx from 'clsx';

const DEFAULT_CLASS = 'react-tabs__tab-panel';
const defaultProps = {
className: DEFAULT_CLASS,
forceRender: false,
selectedClassName: `${DEFAULT_CLASS}--selected`,
};

/*
Left for TS migration
Expand All @@ -23,20 +18,16 @@ const propTypes = {
selectedClassName: PropTypes.string,
};
*/
const TabPanel = (props) => {
const {
children,
className,
forceRender,
id,
selected,
selectedClassName,
...attributes
} = {
...defaultProps,
...props,
};

const TabPanel = ({
children,
className = DEFAULT_CLASS,
forceRender = false,
selectedClassName = `${DEFAULT_CLASS}--selected`,
id,
selected,
...attributes
}) => {
return (
<div
{...attributes}
Expand Down
97 changes: 46 additions & 51 deletions src/components/Tabs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,11 @@ import { getTabsCount } from '../helpers/count';

const MODE_CONTROLLED = 0;
const MODE_UNCONTROLLED = 1;

const propTypes = {
children: childrenPropType,
onSelect: onSelectPropType,
selectedIndex: selectedIndexPropType,
/*
Left for TS migration
className: PropTypes.oneOfType([
PropTypes.string,
PropTypes.array,
PropTypes.object,
]),
defaultFocus: PropTypes.bool,
defaultIndex: PropTypes.number,
direction: PropTypes.oneOf(['rtl', 'ltr']),
disabledTabClassName: PropTypes.string,
disableUpDownKeys: PropTypes.bool,
disableLeftRightKeys: PropTypes.bool,
domRef: PropTypes.func,
environment: PropTypes.object,
focusTabOnClick: PropTypes.bool,
forceRenderTabPanel: PropTypes.bool,
selectedTabClassName: PropTypes.string,
selectedTabPanelClassName: PropTypes.string,*/
};
const defaultProps = {
defaultFocus: false,
focusTabOnClick: true,
forceRenderTabPanel: false,
selectedIndex: null,
defaultIndex: null,
environment: null,
disableUpDownKeys: false,
disableLeftRightKeys: false,
};

const getModeFromProps = (props) => {
Expand All @@ -69,23 +41,32 @@ For more information about controlled and uncontrolled mode of react-tabs see ht
* focus: Because we never remove focus from the Tabs this state is only used to indicate that we should focus the current tab.
* It is initialized from the prop defaultFocus, and after the first render it is reset back to false. Later it can become true again when using keys to navigate the tabs.
*/
const Tabs = (props) => {
checkPropTypes(propTypes, props, 'prop', 'Tabs');
const {
children,
defaultFocus,
defaultIndex,
focusTabOnClick,
onSelect,
...attributes
} = {
...defaultProps,
...props,
};
const Tabs = ({
children,
defaultFocus = false,
defaultIndex = null,
focusTabOnClick = true,
forceRenderTabPanel = false,
selectedIndex = null,
environment = null,
disableUpDownKeys = false,
disableLeftRightKeys = false,
onSelect,
...attributes
}) => {
checkPropTypes(propTypes, { children, onSelect, selectedIndex }, 'prop', 'Tabs');

// Check for conflicting props
if (process.env.NODE_ENV !== 'production' && selectedIndex !== null && defaultIndex !== null) {
console.error(
'The prop `selectedIndex` cannot be used together with `defaultIndex` in `Tabs`.\n' +
'Either remove `selectedIndex` to let `Tabs` handle the selected tab internally or remove `defaultIndex` to handle it yourself.'
);
}

const [focus, setFocus] = useState(defaultFocus);
const [mode] = useState(getModeFromProps(attributes));
const [selectedIndex, setSelectedIndex] = useState(
const [mode] = useState(getModeFromProps({ selectedIndex }));
const [selectedIndexState, setSelectedIndexState] = useState(
mode === MODE_UNCONTROLLED ? defaultIndex || 0 : null,
);

Expand All @@ -98,14 +79,14 @@ const Tabs = (props) => {
// Ensure that we handle removed tabs and don't let selectedIndex get out of bounds
const tabsCount = getTabsCount(children);
useEffect(() => {
if (selectedIndex != null) {
if (selectedIndexState != null) {
const maxTabIndex = Math.max(0, tabsCount - 1);
setSelectedIndex(Math.min(selectedIndex, maxTabIndex));
setSelectedIndexState(Math.min(selectedIndexState, maxTabIndex));
}
}, [tabsCount]);
}

checkForIllegalModeChange(attributes, mode);
checkForIllegalModeChange({ selectedIndex }, mode);

const handleSelected = (index, last, event) => {
// Call change event handler
Expand All @@ -121,21 +102,35 @@ const Tabs = (props) => {

if (mode === MODE_UNCONTROLLED) {
// Update selected index
setSelectedIndex(index);
setSelectedIndexState(index);
}
};

let subProps = { ...props, ...attributes };
let subProps = {
children,
defaultFocus,
defaultIndex,
focusTabOnClick,
forceRenderTabPanel,
selectedIndex,
environment,
disableUpDownKeys,
disableLeftRightKeys,
onSelect,
...attributes
};

subProps.focus = focus;
subProps.onSelect = handleSelected;

if (selectedIndex != null) {
subProps.selectedIndex = selectedIndex;
if (selectedIndexState != null) {
subProps.selectedIndex = selectedIndexState;
}

delete subProps.defaultFocus;
delete subProps.defaultIndex;
delete subProps.focusTabOnClick;

return <UncontrolledTabs {...subProps}>{children}</UncontrolledTabs>;
};

Expand Down
Loading