Skip to content

Feat/change tab controller center selected logic #1103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ca6b157
Move TabBar to functional component
M-i-k-e-l Dec 27, 2020
2377b58
Fix Fader in RTL
M-i-k-e-l Dec 27, 2020
6b907ce
Merge branch 'master' into typescript/tab-controller-move-to-function…
M-i-k-e-l Dec 29, 2020
ecbc6e0
change tab controller center selected logic (and move it to a helper…
M-i-k-e-l Dec 29, 2020
3f268b1
Fix import (cycle) + generate types
M-i-k-e-l Dec 29, 2020
cd65641
Change the DYNAMIC logic (did not look good when scrolling pages)
M-i-k-e-l Dec 29, 2020
8aaccdd
Merge branch 'master' into feat/change-tab-controller-center-selected…
M-i-k-e-l Jan 3, 2021
d79af43
Revert merging wrong commit
M-i-k-e-l Jan 3, 2021
462647b
FocusItemsHelper --> useFocusItemsHelper
M-i-k-e-l Jan 4, 2021
6b8c9ea
Add (and use) useScrollEnabler and useScrollReached hooks
M-i-k-e-l Jan 4, 2021
57d42f0
Move hooks to the hooks folder
M-i-k-e-l Jan 6, 2021
ae027dc
Merge branch 'master' into feat/change-tab-controller-center-selected…
M-i-k-e-l Jan 6, 2021
c7a677e
sideSpacing --> outerSpacing
M-i-k-e-l Jan 6, 2021
7d7c8e6
Fix typo
M-i-k-e-l Jan 6, 2021
c09acd8
renderSelectedIndicator --> selectedIndicator
M-i-k-e-l Jan 6, 2021
c2bf678
Move useFocusItemsHelper
M-i-k-e-l Jan 6, 2021
7e25406
Merge branch 'master' into feat/change-tab-controller-center-selected…
M-i-k-e-l Jan 18, 2021
60511a6
Rename useFocusItemsHelper --> useScrollIToItem
M-i-k-e-l Jan 18, 2021
9ace954
Fix typo
M-i-k-e-l Jan 18, 2021
c3697e0
Create useScrollTo hook
M-i-k-e-l Jan 18, 2021
f9f5c97
Refactor Props and ResultProps --> better names
M-i-k-e-l Jan 18, 2021
a7a9d82
Merge branch 'master' into feat/change-tab-controller-center-selected…
ethanshar Jan 21, 2021
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
2 changes: 2 additions & 0 deletions demo/src/screens/componentScreens/FaderScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import _ from 'lodash';
import React, {Component} from 'react';
import {StyleSheet, ScrollView} from 'react-native';
import {Colors, Text, View, Fader, withScrollReached, WithScrollReachedProps} from 'react-native-ui-lib';
// @ts-ignore
import {renderHeader} from '../ExampleScreenPresenter';

const numberOfItems = 3;
Expand All @@ -10,6 +11,7 @@ const itemWidth = 100;
const itemHeight = 100;
const tintColor = undefined;

// @ts-ignore
const horizontal = faderPosition === Fader.position.START || faderPosition === Fader.position.END;

class FaderScreen extends Component<WithScrollReachedProps> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,15 @@ class TabControllerScreen extends Component<{}, State> {
this.state.items = this.generateTabItems();
}

generateTabItems = (fewItems = this.state.fewItems, centerSelected = this.state.centerSelected): TabControllerItemProps[] => {
generateTabItems = (fewItems = this.state.fewItems): TabControllerItemProps[] => {
let items: TabControllerItemProps[] = _.chain(TABS)
.take(fewItems ? 3 : TABS.length)
.map<TabControllerItemProps>(tab => ({label: tab, key: tab}))
.value();

const addItem: TabControllerItemProps = {icon: Assets.icons.demo.add, key: 'add', ignore: true, width: 60, onPress: this.onAddItem};

if (!centerSelected) {
items = [...items, addItem];
}
return items;
return [...items, addItem];
};

componentDidMount() {
Expand Down Expand Up @@ -83,7 +80,7 @@ class TabControllerScreen extends Component<{}, State> {
toggleCenterSelected = () => {
const {fewItems, centerSelected} = this.state;
this.setState({
items: this.generateTabItems(fewItems, !centerSelected),
items: this.generateTabItems(fewItems),
centerSelected: !centerSelected,
key: Date.now()
});
Expand Down
3 changes: 2 additions & 1 deletion generatedTypes/components/fader/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/// <reference types="react" />
import { ImageProps } from '../image';
export declare enum FaderPosition {
/**
* @deprecated please use START instead
Expand All @@ -13,7 +14,7 @@ export declare enum FaderPosition {
TOP = "TOP",
BOTTOM = "BOTTOM"
}
export declare type FaderProps = {
export declare type FaderProps = Pick<ImageProps, 'supportRTL'> & {
/**
* Whether the fader is visible (default is true)
*/
Expand Down
4 changes: 3 additions & 1 deletion generatedTypes/components/tabController/FadedScrollView.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React from 'react';
import { ViewProps, ScrollViewProps } from 'react-native';
import { ForwardRefInjectedProps } from '../../commons/forwardRef';
export declare type FadedScrollViewProps = ViewProps & ScrollViewProps & {
children?: React.ReactNode | React.ReactNode[];
};
declare const _default: React.ComponentClass<FadedScrollViewProps, any> | React.FunctionComponent<FadedScrollViewProps>;
declare type Props = FadedScrollViewProps & ForwardRefInjectedProps;
declare const _default: React.ComponentType<Props>;
export default _default;
7 changes: 3 additions & 4 deletions generatedTypes/components/tabController/TabBarItem.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PureComponent } from 'react';
import { TextStyle, LayoutRectangle, LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';
import { /* processColor, */ TextStyle, LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';
import _ from 'lodash';
import Reanimated from 'react-native-reanimated';
import { State } from 'react-native-gesture-handler';
Expand Down Expand Up @@ -86,7 +86,7 @@ interface Props extends TabControllerItemProps {
targetPage: any;
state: State;
currentPage: Reanimated.Adaptable<number>;
onLayout: (layout: Partial<LayoutRectangle>, index: number) => void;
onLayout?: (event: LayoutChangeEvent, index: number) => void;
}
/**
* @description: TabController's TabBarItem
Expand All @@ -102,8 +102,7 @@ export default class TabBarItem extends PureComponent<Props> {
private itemWidth?;
private itemRef;
constructor(props: Props);
onStateChange: (...args: any[]) => void;
onLayout: ({ nativeEvent: { layout: { width } } }: LayoutChangeEvent) => void;
onLayout: (event: LayoutChangeEvent) => void;
onPress: () => void;
getItemStyle(): any[];
getLabelStyle(): (TextStyle | _.Dictionary<Reanimated.Node<number> | Reanimated.Node<string | number | boolean> | Reanimated.Node<"normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900"> | undefined> | undefined)[];
Expand Down
4 changes: 4 additions & 0 deletions generatedTypes/hooks/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export { default as useToggleValue } from './useToggleValue';
export { default as useDidUpdate } from './useDidUpdate';
export { default as useScrollEnabler } from './useScrollEnabler';
export { default as useScrollReached } from './useScrollReached';
export { default as useScrollToItem } from './useScrollToItem';
export { default as useScrollTo } from './useScrollTo';
23 changes: 23 additions & 0 deletions generatedTypes/hooks/useScrollEnabler/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { LayoutChangeEvent } from 'react-native';
export declare type ScrollEnablerProps = {
/**
* Whether the scroll is horizontal (default is false).
*/
horizontal?: boolean;
};
export declare type ScrollEnablerResultProps = {
/**
* onContentSizeChange callback (should be set to your onContentSizeChange).
*/
onContentSizeChange: (contentWidth: number, contentHeight: number) => void;
/**
* onLayout callback (should be set to your onLayout).
*/
onLayout: (event: LayoutChangeEvent) => void;
/**
* Whether the scroll should be enabled (should be set to your scrollEnabled).
*/
scrollEnabled: boolean;
};
declare const useScrollEnabler: (props?: ScrollEnablerProps) => ScrollEnablerResultProps;
export default useScrollEnabler;
28 changes: 28 additions & 0 deletions generatedTypes/hooks/useScrollReached/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
export declare type ScrollEnablerProps = {
/**
* Whether the scroll is horizontal (default is false).
*/
horizontal?: boolean;
/**
* Allows to be notified prior to actually reaching the start \ end of the scroll (by the threshold).
* Should be a positive value.
*/
threshold?: number;
};
export declare type ScrollEnablerResultProps = {
/**
* onScroll callback (should be set to your onScroll).
*/
onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
/**
* Is the scroll at the start (or equal\smaller than the threshold if one was given)
*/
isScrollAtStart?: boolean;
/**
* Is the scroll at the end (or equal\greater than the threshold if one was given)
*/
isScrollAtEnd?: boolean;
};
declare const useScrollReached: (props?: ScrollEnablerProps) => ScrollEnablerResultProps;
export default useScrollReached;
27 changes: 27 additions & 0 deletions generatedTypes/hooks/useScrollTo/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { RefObject } from 'react';
import { ScrollView, FlatList } from 'react-native';
export declare type ScrollToSupportedViews = ScrollView | FlatList;
export declare type ScrollToProps<T extends ScrollToSupportedViews> = {
/**
* A reference to the ScrollView (or FlatList) which the items are in
*/
scrollViewRef?: RefObject<T>;
/**
* Is the scroll view horizontal (default is true)
*/
horizontal?: boolean;
};
export declare type ScrollToResultProps<T extends ScrollToSupportedViews> = {
/**
* A reference to the ScrollView (or FlatList) which the items are in (from the props or a created one)
*/
scrollViewRef: RefObject<T>;
/**
* scrollTo callback.
* scrollToOffset - the x or y to scroll to.
* animated - should the scroll be animated (default is true)
*/
scrollTo: (scrollToOffset: number, animated?: boolean) => void;
};
declare const useScrollTo: <T extends ScrollToSupportedViews>(props: ScrollToProps<T>) => ScrollToResultProps<T>;
export default useScrollTo;
52 changes: 52 additions & 0 deletions generatedTypes/hooks/useScrollToItem/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { LayoutChangeEvent } from 'react-native';
import { ScrollToProps, ScrollToSupportedViews, ScrollToResultProps } from '../useScrollTo';
export declare enum OffsetType {
CENTER = "CENTER",
DYNAMIC = "DYNAMIC",
LEFT = "LEFT",
RIGHT = "RIGHT"
}
export declare type ScrollToItemProps<T extends ScrollToSupportedViews> = Pick<ScrollToProps<T>, 'scrollViewRef'> & {
/**
* The number of items
*/
itemsCount: number;
/**
* The selected item's index
*/
selectedIndex?: number;
/**
* Where would the item be located (default to CENTER)
*/
offsetType?: OffsetType;
/**
* Add a margin to the offset (default to true)
* This gives a better UX
* Not relevant to OffsetType.CENTER
*/
addOffsetMargin?: boolean;
/**
* How much space (padding \ margin) is there on the left\right of the items
*/
outerSpacing?: number;
/**
* How much space (padding \ margin) is there between each item
*/
innerSpacing?: number;
};
export declare type ScrollToItemResultProps<T extends ScrollToSupportedViews> = Pick<ScrollToResultProps<T>, 'scrollViewRef'> & {
/**
* This should be called by each ot the items' onLayout
*/
onItemLayout: (event: LayoutChangeEvent, index: number) => void;
/**
* The items' width
*/
itemsWidths: number[];
/**
* Use in order to focus the item with the specified index
*/
focusIndex: (index: number, animated?: boolean) => void;
};
declare const useScrollToItem: <T extends ScrollToSupportedViews>(props: ScrollToItemProps<T>) => ScrollToItemResultProps<T>;
export default useScrollToItem;
56 changes: 24 additions & 32 deletions src/commons/withScrollEnabler.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React, {useState, useCallback, useRef} from 'react';
// eslint-disable-next-line no-unused-vars
import {FlatListProps, ScrollViewProps, LayoutChangeEvent} from 'react-native';
// eslint-disable-next-line no-unused-vars
import forwardRef, {ForwardRefInjectedProps} from './forwardRef';
//@ts-ignore
import hoistStatics from 'hoist-non-react-statics';
Expand All @@ -21,9 +19,7 @@ export type WithScrollEnablerProps = {

type PropTypes = ForwardRefInjectedProps & SupportedViewsProps;

function withScrollEnabler<PROPS, STATICS = {}>(
WrappedComponent: React.ComponentType<PROPS & WithScrollEnablerProps>
): React.ComponentType<PROPS> & STATICS {
function withScrollEnabler<PROPS, STATICS = {}>(WrappedComponent: React.ComponentType<PROPS & WithScrollEnablerProps>): React.ComponentType<PROPS> & STATICS {
const ScrollEnabler: React.FunctionComponent<PROPS & PropTypes> = (props: PROPS & PropTypes) => {
const [scrollEnabled, setScrollEnabled] = useState(true);
const contentSize = useRef(0);
Expand All @@ -36,36 +32,32 @@ function withScrollEnabler<PROPS, STATICS = {}>(
}
}, [scrollEnabled]);

const onContentSizeChange = useCallback(
(contentWidth: number, contentHeight: number) => {
const size = props.horizontal ? contentWidth : contentHeight;
if (size !== contentSize.current) {
contentSize.current = size;
if (layoutSize.current > 0) {
checkScroll();
}
const onContentSizeChange = useCallback((contentWidth: number, contentHeight: number) => {
const size = props.horizontal ? contentWidth : contentHeight;
if (size !== contentSize.current) {
contentSize.current = size;
if (layoutSize.current > 0) {
checkScroll();
}
},
[props.horizontal, checkScroll]
);
}
},
[props.horizontal, checkScroll]);

const onLayout = useCallback(
(event: LayoutChangeEvent) => {
const {
nativeEvent: {
layout: {width, height}
}
} = event;
const size = props.horizontal ? width : height;
if (size !== layoutSize.current) {
layoutSize.current = size;
if (contentSize.current > 0) {
checkScroll();
}
const onLayout = useCallback((event: LayoutChangeEvent) => {
const {
nativeEvent: {
layout: {width, height}
}
},
[props.horizontal, checkScroll]
);
} = event;
const size = props.horizontal ? width : height;
if (size !== layoutSize.current) {
layoutSize.current = size;
if (contentSize.current > 0) {
checkScroll();
}
}
},
[props.horizontal, checkScroll]);

return (
<WrappedComponent
Expand Down
Loading