+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/tabs/demo/index.vue b/components/tabs/demo/index.vue
index 7632dcfba..22b7f6a25 100644
--- a/components/tabs/demo/index.vue
+++ b/components/tabs/demo/index.vue
@@ -53,17 +53,19 @@ export default {
return (
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/tabs/demo/slide.md b/components/tabs/demo/slide.md
index 0fb24e99d..e22000d0c 100644
--- a/components/tabs/demo/slide.md
+++ b/components/tabs/demo/slide.md
@@ -22,17 +22,7 @@ In order to fit in more tabs, they can slide left and right (or up and down).
@prevClick="callback"
@nextClick="callback"
>
- Content of tab 1
- Content of tab 2
- Content of tab 3
- Content of tab 4
- Content of tab 5
- Content of tab 6
- Content of tab 7
- Content of tab 8
- Content of tab 9
- Content of tab 10
- Content of tab 11
+ Content of tab {{i}}
diff --git a/components/timeline/Timeline.jsx b/components/timeline/Timeline.jsx
index cf8261d15..79291138a 100644
--- a/components/timeline/Timeline.jsx
+++ b/components/timeline/Timeline.jsx
@@ -19,7 +19,7 @@ export const TimelineProps = {
pending: PropTypes.any,
pendingDot: PropTypes.string,
reverse: PropTypes.bool,
- mode: PropTypes.oneOf(['left', 'alternate', 'right']),
+ mode: PropTypes.oneOf(['left', 'alternate', 'right', '']),
};
export default {
diff --git a/components/vc-tabs/src/InkTabBarNode.jsx b/components/vc-tabs/src/InkTabBarNode.jsx
index b47d3c8d4..c786cc9c3 100644
--- a/components/vc-tabs/src/InkTabBarNode.jsx
+++ b/components/vc-tabs/src/InkTabBarNode.jsx
@@ -1,9 +1,16 @@
import PropTypes from '../../_util/vue-types';
-import { setTransform, isTransformSupported, getLeft, getTop, getActiveIndex } from './utils';
+import {
+ setTransform,
+ isTransform3dSupported,
+ getLeft,
+ getStyle,
+ getTop,
+ getActiveIndex,
+} from './utils';
import BaseMixin from '../../_util/BaseMixin';
function componentDidUpdate(component, init) {
- const { styles = {}, panels, activeKey } = component.$props;
+ const { styles = {}, panels, activeKey, direction } = component.$props;
const rootNode = component.getRef('root');
const wrapNode = component.getRef('nav') || rootNode;
const inkBarNode = component.getRef('inkBar');
@@ -17,7 +24,7 @@ function componentDidUpdate(component, init) {
}
if (activeTab) {
const tabNode = activeTab;
- const transformSupported = isTransformSupported(inkBarNodeStyle);
+ const transformSupported = isTransform3dSupported(inkBarNodeStyle);
// Reset current style
setTransform(inkBarNodeStyle, '');
@@ -42,6 +49,9 @@ function componentDidUpdate(component, init) {
left += (tabNode.offsetWidth - width) / 2;
}
}
+ if (direction === 'rtl') {
+ left = getStyle(tabNode, 'margin-left') - left;
+ }
// use 3d gpu to optimize render
if (transformSupported) {
setTransform(inkBarNodeStyle, `translate3d(${left}px,0,0)`);
@@ -78,6 +88,7 @@ export default {
type: Boolean,
default: true,
},
+ direction: PropTypes.string,
prefixCls: String,
styles: Object,
tabBarPosition: String,
diff --git a/components/vc-tabs/src/ScrollableTabBarNode.jsx b/components/vc-tabs/src/ScrollableTabBarNode.jsx
index 1eb22070b..d1337f5f3 100644
--- a/components/vc-tabs/src/ScrollableTabBarNode.jsx
+++ b/components/vc-tabs/src/ScrollableTabBarNode.jsx
@@ -1,9 +1,9 @@
-import addDOMEventListener from 'add-dom-event-listener';
import debounce from 'lodash/debounce';
+import ResizeObserver from 'resize-observer-polyfill';
import PropTypes from '../../_util/vue-types';
import BaseMixin from '../../_util/BaseMixin';
import { getComponentFromProp } from '../../_util/props-util';
-import { setTransform, isTransformSupported } from './utils';
+import { setTransform, isTransform3dSupported } from './utils';
function noop() {}
export default {
@@ -19,6 +19,7 @@ export default {
navWrapper: PropTypes.func.def(arg => arg),
prevIcon: PropTypes.any,
nextIcon: PropTypes.any,
+ direction: PropTypes.string,
},
data() {
@@ -45,7 +46,8 @@ export default {
this.setNextPrev();
this.scrollToActiveTab();
}, 200);
- this.resizeEvent = addDOMEventListener(window, 'resize', this.debouncedResize);
+ this.resizeObserver = new ResizeObserver(this.debouncedResize);
+ this.resizeObserver.observe(this.$props.getRef('container'));
});
},
@@ -57,8 +59,8 @@ export default {
},
beforeDestroy() {
- if (this.resizeEvent) {
- this.resizeEvent.remove();
+ if (this.resizeObserver) {
+ this.resizeObserver.remove();
}
if (this.debouncedResize && this.debouncedResize.cancel) {
this.debouncedResize.cancel();
@@ -151,13 +153,13 @@ export default {
},
setOffset(offset, checkNextPrev = true) {
- const target = Math.min(0, offset);
+ let target = Math.min(0, offset);
if (this.offset !== target) {
this.offset = target;
let navOffset = {};
const tabBarPosition = this.$props.tabBarPosition;
const navStyle = this.$props.getRef('nav').style;
- const transformSupported = isTransformSupported(navStyle);
+ const transformSupported = isTransform3dSupported(navStyle);
if (tabBarPosition === 'left' || tabBarPosition === 'right') {
if (transformSupported) {
navOffset = {
@@ -170,6 +172,9 @@ export default {
};
}
} else if (transformSupported) {
+ if (this.$props.direction === 'rtl') {
+ target = -target;
+ }
navOffset = {
value: `translate3d(${target}px,0,0)`,
};
diff --git a/components/vc-tabs/src/TabBarTabsNode.jsx b/components/vc-tabs/src/TabBarTabsNode.jsx
index e01b4ee43..3fb7f17a5 100644
--- a/components/vc-tabs/src/TabBarTabsNode.jsx
+++ b/components/vc-tabs/src/TabBarTabsNode.jsx
@@ -17,6 +17,7 @@ export default {
getRef: PropTypes.func.def(noop),
renderTabBarNode: PropTypes.func,
tabBarPosition: PropTypes.string,
+ direction: PropTypes.string,
},
render() {
const {
@@ -26,6 +27,7 @@ export default {
tabBarGutter,
saveRef,
tabBarPosition,
+ direction,
} = this.$props;
const rst = [];
const renderTabBarNode = this.renderTabBarNode || this.$scopedSlots.renderTabBarNode;
@@ -56,8 +58,9 @@ export default {
const tab = getComponentFromProp(child, 'tab');
let gutter = tabBarGutter && index === children.length - 1 ? 0 : tabBarGutter;
gutter = typeof gutter === 'number' ? `${gutter}px` : gutter;
+ const marginProperty = direction === 'rtl' ? 'marginLeft' : 'marginRight';
const style = {
- [isVertical(tabBarPosition) ? 'marginBottom' : 'marginRight']: gutter,
+ [isVertical(tabBarPosition) ? 'marginBottom' : marginProperty]: gutter,
};
warning(tab !== undefined, 'There must be `tab` property or slot on children of Tabs.');
let node = (
diff --git a/components/vc-tabs/src/TabContent.jsx b/components/vc-tabs/src/TabContent.jsx
index 515d16b9b..35e3d340d 100644
--- a/components/vc-tabs/src/TabContent.jsx
+++ b/components/vc-tabs/src/TabContent.jsx
@@ -17,6 +17,8 @@ export default {
},
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
tabBarPosition: String,
+ direction: PropTypes.string,
+ destroyInactiveTabPane: PropTypes.bool,
},
computed: {
classes() {
@@ -62,7 +64,7 @@ export default {
if (activeIndex !== -1) {
const animatedStyle = animatedWithMargin
? getMarginStyle(activeIndex, tabBarPosition)
- : getTransformPropValue(getTransformByIndex(activeIndex, tabBarPosition));
+ : getTransformPropValue(getTransformByIndex(activeIndex, tabBarPosition, direction));
style = animatedStyle;
} else {
style = {
diff --git a/components/vc-tabs/src/Tabs.jsx b/components/vc-tabs/src/Tabs.jsx
index e1760bba9..ea9570169 100644
--- a/components/vc-tabs/src/Tabs.jsx
+++ b/components/vc-tabs/src/Tabs.jsx
@@ -42,6 +42,7 @@ export default {
activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
__propsSymbol__: PropTypes.any,
+ direction: PropTypes.string.def('ltr'),
},
data() {
const props = getOptionProps(this);
@@ -177,6 +178,7 @@ export default {
raf.cancel(this.sentinelId);
this.sentinelId = raf(() => {
+ if (this.destroy) return;
this.$forceUpdate();
});
},
@@ -190,10 +192,12 @@ export default {
renderTabContent,
renderTabBar,
destroyInactiveTabPane,
+ direction,
} = props;
const cls = {
[prefixCls]: 1,
[`${prefixCls}-${tabBarPosition}`]: 1,
+ [`${prefixCls}-rtl`]: direction === 'rtl',
};
this.tabBar = renderTabBar();
@@ -204,6 +208,7 @@ export default {
tabBarPosition,
panels: props.children,
activeKey: this.$data._activeKey,
+ direction,
},
on: {
keydown: this.onNavKeyDown,
@@ -217,6 +222,7 @@ export default {
tabBarPosition,
activeKey: this.$data._activeKey,
destroyInactiveTabPane,
+ direction,
},
on: {
change: this.setActiveKey,
diff --git a/components/vc-tabs/src/index.js b/components/vc-tabs/src/index.js
index 14cc18843..91f7e76d6 100755
--- a/components/vc-tabs/src/index.js
+++ b/components/vc-tabs/src/index.js
@@ -1,4 +1,4 @@
-// based on rc-tabs 9.6.1
+// based on rc-tabs 9.7.0
import ref from 'vue-ref';
import Vue from 'vue';
import Tabs from './Tabs';
diff --git a/components/vc-tabs/src/utils.js b/components/vc-tabs/src/utils.js
index 0276c6d39..2aaac3152 100644
--- a/components/vc-tabs/src/utils.js
+++ b/components/vc-tabs/src/utils.js
@@ -29,8 +29,10 @@ export function setTransform(style, v) {
style.mozTransform = v;
}
-export function isTransformSupported(style) {
- return 'transform' in style || 'webkitTransform' in style || 'MozTransform' in style;
+export function isTransform3dSupported(style) {
+ return (
+ ('transform' in style || 'webkitTransform' in style || 'MozTransform' in style) && window.atob
+ );
}
export function setTransition(style, v) {
@@ -50,8 +52,11 @@ export function isVertical(tabBarPosition) {
return tabBarPosition === 'left' || tabBarPosition === 'right';
}
-export function getTransformByIndex(index, tabBarPosition) {
+export function getTransformByIndex(index, tabBarPosition, direction = 'ltr') {
const translate = isVertical(tabBarPosition) ? 'translateY' : 'translateX';
+ if (!isVertical(tabBarPosition) && direction === 'rtl') {
+ return `${translate}(${index * 100}%) translateZ(0)`;
+ }
return `${translate}(${-index * 100}%) translateZ(0)`;
}