Skip to content

Commit

Permalink
Merge pull request #758 from shoutem/release/5.6.0
Browse files Browse the repository at this point in the history
release 5.6.0 -> master
  • Loading branch information
sstimac authored Oct 12, 2022
2 parents 20b641d + 5a4ad0a commit e8f30b2
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 12 deletions.
78 changes: 74 additions & 4 deletions components/TabMenu/TabMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,91 @@ class TabMenu extends PureComponent {
super(props);

autoBindReact(this);

this.state = {
itemWidths: {},
scrollOffset: 0,
};
}

handleOptionSelected(option) {
handleOptionSelected(key, option) {
const { onOptionSelected } = this.props;
const { scrollOffset, itemWidths, viewportHorizontal } = this.state;

let itemStart = 0;

_.forEach(itemWidths, (itemWidth, index) => {
if (index < key) {
itemStart += itemWidth;
}
});

const itemEnd = itemStart + itemWidths[key];

LayoutAnimation.easeInEaseOut();
onOptionSelected(option);

if (itemEnd > _.last(viewportHorizontal)) {
const extraScroll = itemEnd - _.last(viewportHorizontal);

this.scroll.scrollTo({
x: extraScroll + scrollOffset,
y: 0,
animated: true,
});
}

if (itemStart < _.head(viewportHorizontal)) {
const extraScroll = _.head(viewportHorizontal) - itemStart;

this.scroll.scrollTo({
x: scrollOffset - extraScroll,
y: 0,
animated: true,
});
}
}

handleItemLayout(key, width) {
const { itemWidths } = this.state;

this.setState({
itemWidths: {
...itemWidths,
[key]: width,
},
});
}

handleScroll({
nativeEvent: {
contentOffset: { x },
layoutMeasurement: { width },
},
}) {
this.setState({ scrollOffset: x, viewportHorizontal: [x, x + width] });
}

handleScrollLayout({
nativeEvent: {
layout: { width },
},
}) {
this.setState({ viewportHorizontal: [0, width] });
}

renderOption(option) {
renderOption(option, key) {
const { selectedOption } = this.props;

const isSelected = selectedOption && option.title === selectedOption.title;

return (
<TabMenuItem
key={option.title}
key={key}
isSelected={isSelected}
item={option}
onItemPressed={this.handleOptionSelected}
onItemPressed={option => this.handleOptionSelected(key, option)}
onLayoutMeasured={width => this.handleItemLayout(key, width)}
/>
);
}
Expand All @@ -43,6 +108,11 @@ class TabMenu extends PureComponent {
<ScrollView
horizontal
contentContainerStyle={style.container}
onScroll={this.handleScroll}
onLayout={this.handleScrollLayout}
ref={ref => {
this.scroll = ref;
}}
showsHorizontalScrollIndicator={false}
style={style.list}
>
Expand Down
17 changes: 14 additions & 3 deletions components/TabMenu/TabMenuItem.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { PureComponent } from 'react';
import { LayoutAnimation } from 'react-native';
import autoBindReact from 'auto-bind/react';
import _ from 'lodash';
import PropTypes from 'prop-types';
import { connectStyle } from '@shoutem/theme';
import { Text } from '../Text';
Expand All @@ -26,7 +25,7 @@ class TabMenuItem extends PureComponent {
onItemPressed(item);
}

handleLayout({
handleTextLayout({
nativeEvent: {
layout: { width },
},
Expand All @@ -35,18 +34,29 @@ class TabMenuItem extends PureComponent {
this.setState({ baseWidth: width });
}

handleContainerLayout({
nativeEvent: {
layout: { width },
},
}) {
const { onLayoutMeasured } = this.props;

onLayoutMeasured(width);
}

render() {
const { style, isSelected, item } = this.props;
const { baseWidth } = this.state;

return (
<TouchableOpacity
onPress={this.handleItemPressed}
onLayout={this.handleContainerLayout}
styleName="vertical h-center"
>
<Text
style={[style.text, isSelected && style.selectedText]}
onLayout={this.handleLayout}
onLayout={this.handleTextLayout}
>
{item.title}
</Text>
Expand All @@ -58,6 +68,7 @@ class TabMenuItem extends PureComponent {

TabMenuItem.propTypes = {
style: PropTypes.object.isRequired,
onLayoutMeasured: PropTypes.func.isRequired,
isSelected: PropTypes.bool,
item: optionShape,
onItemPressed: PropTypes.func,
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shoutem/ui",
"version": "5.5.0",
"version": "5.6.0",
"description": "Styleable set of components for React Native applications",
"scripts": {
"lint": "eslint .",
Expand Down
3 changes: 1 addition & 2 deletions theme.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Dimensions, Platform, StatusBar, StyleSheet } from 'react-native';
import { Dimensions, Platform, StyleSheet } from 'react-native';
import {
changeColorAlpha,
createSharedStyle,
Expand Down Expand Up @@ -2899,7 +2899,6 @@ export default () => {
borderRadius: 1,
flexDirection: 'row',
marginBottom: 8,
marginLeft: 8,
},
text: {
marginTop: 12,
Expand Down

0 comments on commit e8f30b2

Please sign in to comment.