Skip to content

Commit 863588e

Browse files
1) del tablistID prop from tabs com
2) move createPopper and getPopperMaxHeight files into popper folder 3) del buttonClassName,popperClassName,TabsComponent,popupContainerID and btnAriaProps from button com and add components prop to it
1 parent 622fc91 commit 863588e

File tree

13 files changed

+130
-74
lines changed

13 files changed

+130
-74
lines changed

src/components/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import TablistOverflow, {tablistOverflowPropsManager} from '../tablistOverflow/t
99
import TablistOverflowFactory from '../tablistOverflow/tablistOverflow.factory.js';
1010
import Tabs, {TabsPropsManager} from '../tabs/tabs.js';
1111
import TabsFactory from '../tabs/tabs.factory.js';
12-
import Tab, {tabPropsManager, tabInnerPropsManager, closeIconPropsManager} from '../tab/tab.js';
12+
import Tab, {tabPropsManager, tabInnerPropsManager, closeIconPropsManager, memomizeTab} from '../tab/tab.js';
1313
import TabFactory from '../tab/tab.factory.js';
14-
import memomizeTab from '../tab/memomizeTab.js';
1514
import {useApi, useRootState, useForceUpdate} from '../hooks.js';
1615
export default {
1716
TablistView,
@@ -33,8 +32,8 @@ export default {
3332
tabPropsManager,
3433
tabInnerPropsManager,
3534
closeIconPropsManager,
36-
TabFactory,
3735
memomizeTab,
36+
TabFactory,
3837
PanelList,
3938
useApi,
4039
useRootState,

src/plugins/moreButtonPlugin/show-more-tabs/api.js

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
let instanceCounter = 0;
21
const Api = function ({getElManagementIns, btnRef, ctx, setHiddenTabIDs}) {
32
this.api = ctx;
43
this.tablistEl = null;
@@ -8,7 +7,6 @@ const Api = function ({getElManagementIns, btnRef, ctx, setHiddenTabIDs}) {
87
this.tabsCount = null;
98
this.btnRef = btnRef;
109
this._setHiddenTabIDs = setHiddenTabIDs;
11-
this._popupContainerID = `rc-dyn-tabs-popupcontainer_${instanceCounter++}`;
1210
};
1311
Object.assign(Api.prototype, {
1412
setEls: function () {
@@ -166,38 +164,19 @@ Object.assign(Api.prototype, {
166164
const className = tabClass + ' ' + showMoreContainerClass;
167165
return {className, ref: this.btnRef};
168166
},
169-
btnPropsGenerator: function (hiddenTabIDs, TabsComponent, accessibility) {
167+
btnPropsGenerator: function (hiddenTabIDs, components) {
170168
const userButton = this.api.getOption('showMoreButtonComponent');
171-
if (userButton && typeof userButton === 'function') {
169+
if (userButton && typeof userButton === 'function')
172170
return {
173171
hiddenTabIDs: hiddenTabIDs,
174172
instance: this.api.userProxy,
175173
};
176-
}
177-
const {showMoreButtonClass, showMorePopperClass, titleClass, tablistViewClass, verticalClass, rtlClass} =
178-
this.api.optionsManager.setting;
179-
const result = {
180-
hiddenTabIDs: hiddenTabIDs,
181-
popupContainerID: this._popupContainerID, //todo
182-
instance: this.api.userProxy,
183-
buttonClassName: titleClass + ' ' + showMoreButtonClass,
184-
TabsComponent,
185-
popperClassName:
186-
tablistViewClass +
187-
' ' +
188-
verticalClass +
189-
' ' +
190-
(this.api.getOption('direction') == 'rtl' ? rtlClass + ' ' : '') +
191-
showMorePopperClass,
192-
btnAriaProps: {},
193-
};
194-
if (accessibility) {
195-
result.btnAriaProps.tabIndex = 0;
196-
result.btnAriaProps.role = 'button';
197-
result.btnAriaProps['aria-haspopup'] = 'true';
198-
result.btnAriaProps['aria-label'] = 'More tabs'; //todo
199-
}
200-
return result;
174+
else
175+
return {
176+
hiddenTabIDs: hiddenTabIDs,
177+
instance: this.api,
178+
components,
179+
};
201180
},
202181
});
203182
export default Api;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import {forwardRef} from 'react';
2+
let _counter = 0;
3+
export default function Api(components) {
4+
return new (this.helper.module(
5+
function (api) {
6+
this._components = components;
7+
this._api = api;
8+
this._counter = _counter++;
9+
this._buttonID = this._getButtonID();
10+
this._tablistID = this._getTabListID();
11+
this.TabsComponent = this._getTabsComponent();
12+
},
13+
{
14+
_getTabListID: function () {
15+
return `rc-dyn-tabs-popupcontainer_${this._counter}`;
16+
},
17+
_getButtonID: function () {
18+
return `rc-dyn-tabs-more-button-${this._counter}`;
19+
},
20+
btnPropsGenerator: function (onClick, ref, isOpen) {
21+
const result = {
22+
onClick,
23+
ref,
24+
className: this._api.getSetting('titleClass') + ' ' + this._api.getSetting('showMoreButtonClass'),
25+
};
26+
if (this._api.getOption('accessibility')) {
27+
result.tabIndex = 0;
28+
result.role = 'button';
29+
result['aria-haspopup'] = 'true';
30+
result['aria-label'] = 'More tabs'; //todo
31+
result.id = this._buttonID;
32+
result['aria-controls'] = this._tablistID;
33+
result['aria-expanded'] = isOpen;
34+
}
35+
return result;
36+
},
37+
_getTabsComponent: function () {
38+
const buttonID = this._buttonID;
39+
const tablistID = this._tablistID;
40+
const TabsPropsManager = function (ins, props) {
41+
const {dir, isVertical} = props;
42+
const result = {
43+
className: ins.getSetting('tablistClass') + ' ' + ins.getSetting(`${dir}Class`),
44+
};
45+
if (isVertical) {
46+
result.className += ' ' + ins.getSetting('verticalClass');
47+
}
48+
if (ins.getOption('accessibility')) {
49+
result.role = 'menu';
50+
result['aria-labelledby'] = buttonID;
51+
result.id = tablistID;
52+
}
53+
return result;
54+
};
55+
this._components.Tabs = forwardRef(
56+
this._components.TabsFactory.bind(undefined, (ins) => ({
57+
Tab: this._getTabComponent(),
58+
TabsPropsManager: (props) => TabsPropsManager(ins, props),
59+
})),
60+
);
61+
return components.Tabs;
62+
},
63+
_getTabComponent: function () {
64+
return this._components.memomizeTab(
65+
this._components.TabFactory.bind(undefined, (ins) => ({
66+
tabPropsManager: (props) => {
67+
const originalProps = this._components.tabPropsManager(ins, props);
68+
const {
69+
'aria-controls': ariaControls,
70+
'aria-expanded': ariaExpanded,
71+
'aria-selected': ariaSelected,
72+
id,
73+
...rest
74+
} = originalProps;
75+
if (rest.role) {
76+
rest.role = 'menuitem';
77+
}
78+
return rest;
79+
},
80+
tabInnerPropsManager: (props) => this._components.tabInnerPropsManager(ins, props),
81+
closeIconPropsManager: () => this._components.closeIconPropsManager(ins),
82+
})),
83+
);
84+
},
85+
getPopperClassName: function () {
86+
const {showMorePopperClass, tablistViewClass, verticalClass, rtlClass} = this._api.optionsManager.setting;
87+
return (
88+
tablistViewClass +
89+
' ' +
90+
verticalClass +
91+
' ' +
92+
(this._api.getOption('direction') == 'rtl' ? rtlClass + ' ' : '') +
93+
showMorePopperClass
94+
);
95+
},
96+
},
97+
))(this);
98+
}
Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,35 @@
11
import React, {useState, useCallback, useRef, useEffect, useLayoutEffect} from 'react';
22
import PropTypes from 'prop-types';
33
export default function Button(getDeps, props) {
4-
const {popupContainerID} = props;
5-
const {Popper} = getDeps();
4+
const {Popper, Api} = getDeps();
65
const [open, setOpen] = useState(false);
6+
const closePopper = useCallback(() => setOpen(false), []);
77
const btnRef = useRef();
88
const popperRef = useRef();
99
const ref = useRef();
10-
ref.current = ref.current || {
11-
closePopper: () => setOpen(false),
12-
};
10+
ref.current = ref.current || Api.call(props.instance, props.components);
1311
useEffect(() => {
1412
const close = () => setOpen(false);
1513
props.instance.on('onSelect', close);
1614
return () => {
1715
props.instance && props.instance.off && props.instance.off('onSelect', close);
1816
};
1917
}, []);
20-
useLayoutEffect(() => {
21-
if (btnRef.current && props.instance.getOption('accessibility')) {
22-
if (open) {
23-
btnRef.current.setAttribute('aria-expanded', true);
24-
btnRef.current.setAttribute('aria-controls', popupContainerID);
25-
} else {
26-
btnRef.current.setAttribute('aria-expanded', false);
27-
btnRef.current.removeAttribute('aria-controls');
28-
}
29-
}
30-
}, [open, btnRef.current]);
3118
const onClick = useCallback(
3219
(ev) => {
3320
ev.stopPropagation();
34-
window.document.removeEventListener('click', ref.current.closePopper, {once: true});
35-
window.document.addEventListener('click', ref.current.closePopper, {once: true});
21+
window.document.removeEventListener('click', closePopper, {once: true});
22+
window.document.addEventListener('click', closePopper, {once: true});
3623
setOpen(!open);
3724
return () => {
38-
window.document.removeEventListener('click', ref.current.closePopper, {once: true});
25+
window.document.removeEventListener('click', closePopper, {once: true});
3926
};
4027
},
4128
[open],
4229
);
4330
return (
4431
<>
45-
<div onClick={onClick} ref={btnRef} className={props.buttonClassName} {...props.btnAriaProps}>
32+
<div {...ref.current.btnPropsGenerator(onClick, btnRef, open)}>
4633
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512" title="More tabs">
4734
<path
4835
fill="gray"
@@ -53,21 +40,17 @@ export default function Button(getDeps, props) {
5340
{open ? (
5441
<Popper
5542
{...props}
43+
TabsComponent={ref.current.TabsComponent}
5644
ref={popperRef}
5745
btnRef={btnRef}
58-
className={props.popperClassName}
59-
popupContainerID={props.popupContainerID}
46+
className={ref.current.getPopperClassName()}
6047
/>
6148
) : null}
6249
</>
6350
);
6451
}
6552
Button.propTypes /* remove-proptypes */ = {
66-
buttonClassName: PropTypes.string,
67-
popperClassName: PropTypes.string,
6853
instance: PropTypes.object,
6954
hiddenTabIDs: PropTypes.string,
70-
TabsComponent: PropTypes.func,
71-
popupContainerID: PropTypes.string,
72-
btnAriaProps: PropTypes.object,
55+
components: PropTypes.object,
7356
};
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {memo} from 'react';
22
import Popper from './popper';
33
import Button from './button';
4-
const getDeps = () => ({Popper});
4+
import Api from './api.js';
5+
const getDeps = () => ({Popper, Api});
56
export default memo(Button.bind(null, getDeps));

src/plugins/moreButtonPlugin/show-more-tabs/button/popper/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {forwardRef} from 'react';
2-
import createPopper from '../createPopper.js';
3-
import getPopperMaxHeight from '../getPopperMaxHeight.js';
2+
import createPopper from './createPopper.js';
3+
import getPopperMaxHeight from './getPopperMaxHeight.js';
44
import Popper from './popper.js';
55
const clk = (e) => {
66
e.nativeEvent.stopImmediatePropagation();

src/plugins/moreButtonPlugin/show-more-tabs/button/popper/popper.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, {useLayoutEffect} from 'react';
22
import PropTypes from 'prop-types';
33
export default function Popper(getDeps, props, popperRef) {
44
const {createPopper, getPopperMaxHeight, clk} = getDeps();
5-
const {TabsComponent, instance, hiddenTabIDs, btnRef, className, popupContainerID: tablistID} = props;
5+
const {TabsComponent, instance, hiddenTabIDs, btnRef, className} = props;
66
useLayoutEffect(() => {
77
popperRef.current.style.maxHeight = getPopperMaxHeight(btnRef.current, 15) + 'px';
88
const popperIns = createPopper(btnRef.current, popperRef.current);
@@ -20,7 +20,6 @@ export default function Popper(getDeps, props, popperRef) {
2020
openTabIDs={openedTabIDs}
2121
dir={instance.getOption('direction')}
2222
isVertical={true}
23-
tablistID={tablistID}
2423
/>
2524
</div>
2625
</>
@@ -32,5 +31,4 @@ Popper.propTypes /* remove-proptypes */ = {
3231
instance: PropTypes.object,
3332
btnRef: PropTypes.object,
3433
TabsComponent: PropTypes.func,
35-
popupContainerID: PropTypes.string,
3634
};

src/plugins/moreButtonPlugin/show-more-tabs/show-more-tabs.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import React, {useState, useRef, useLayoutEffect} from 'react';
22
import PropTypes from 'prop-types';
33
export default function ShowMoreTabs(getDeps, props) {
44
const {
5-
components: {Tabs: TabsComponent, useRootState, useForceUpdate},
5+
components,
6+
components: {useRootState, useForceUpdate},
67
ctx,
78
ctx: {
89
optionsManager: {options},
@@ -35,12 +36,12 @@ export default function ShowMoreTabs(getDeps, props) {
3536
: Button;
3637
return (
3738
<div {...ins.btnContainerPropsGenerator()}>
38-
<ButtonComponent {...ins.btnPropsGenerator(hiddenTabIDs, TabsComponent, options.accessibility)} />
39+
<ButtonComponent {...ins.btnPropsGenerator(hiddenTabIDs, components)} />
3940
</div>
4041
);
4142
}
4243
ShowMoreTabs.propTypes /* remove-proptypes */ = {
4344
ctx: PropTypes.object,
4445
contexts: PropTypes.object,
45-
TabsComponent: PropTypes.func,
46+
components: PropTypes.object,
4647
};

0 commit comments

Comments
 (0)