diff --git a/src/index.tsx b/src/index.tsx index 39abb17a..9ec07bb9 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -72,6 +72,10 @@ interface SegmentedControlProps { * Badge Text Styles */ badgeTextStyle?: TextStyle; + /** + * The segment component + */ + SegmentComponent?: React.ComponentType; } const defaultShadowStyle = { @@ -95,49 +99,55 @@ const DEFAULT_SPRING_CONFIG = { restDisplacementThreshold: 0.001, }; -const SegmentedControl: React.FC = ({ - segments, - currentIndex, - onChange, - badgeValues = [], - isRTL = false, - containerMargin = 0, +export interface SegmentProps { + /** + * The string value of the segment + */ + segment: string | null; + /** + * The selection state of this segment + */ + selected: boolean; + /** + * The selection state of this segment + */ + badgeValue: number | null; + /** + * Active Segment Text Style + */ + activeTextStyle?: TextStyle; + /** + * InActive Segment Text Style + */ + inactiveTextStyle?: TextStyle; + /** + * The moving Tile Container Styles + */ + tileStyle?: ViewStyle; + /** + * Active Badge Styles + */ + activeBadgeStyle?: ViewStyle; + /** + * Inactive Badge Styles + */ + inactiveBadgeStyle?: ViewStyle; + /** + * Badge Text Styles + */ + badgeTextStyle?: TextStyle; +} + +const DefaultSegment: React.FC = ({ + segment, + selected, + badgeValue, activeTextStyle, inactiveTextStyle, - segmentedControlWrapper, - pressableWrapper, - tileStyle, activeBadgeStyle, inactiveBadgeStyle, badgeTextStyle, -}: SegmentedControlProps) => { - const width = widthPercentageToDP('100%') - containerMargin * 2; - const translateValue = width / segments.length; - const tabTranslateValue = useSharedValue(0); - - // useCallBack with an empty array as input, which will call inner lambda only once and memoize the reference for future calls - const memoizedTabPressCallback = React.useCallback( - (index) => { - onChange(index); - }, - [onChange] - ); - useEffect(() => { - // If phone is set to RTL, make sure the animation does the correct transition. - const transitionMultiplier = isRTL ? -1 : 1; - tabTranslateValue.value = withSpring( - currentIndex * (translateValue * transitionMultiplier), - DEFAULT_SPRING_CONFIG - ); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [currentIndex]); - - const tabTranslateAnimatedStyles = useAnimatedStyle(() => { - return { - transform: [{ translateX: tabTranslateValue.value }], - }; - }); - +}) => { const finalisedActiveTextStyle: TextStyle = { fontSize: 15, fontWeight: '600', @@ -177,6 +187,69 @@ const SegmentedControl: React.FC = ({ ...badgeTextStyle, }; + return ( + + + {segment} + + {badgeValue && ( + + {badgeValue} + + )} + + ); +}; + +const SegmentedControl: React.FC = ({ + segments, + currentIndex, + onChange, + isRTL = false, + containerMargin = 0, + segmentedControlWrapper, + pressableWrapper, + tileStyle, + SegmentComponent = DefaultSegment, + badgeValues = [], + ...rest +}: SegmentedControlProps) => { + const width = widthPercentageToDP('100%') - containerMargin * 2; + const translateValue = width / segments.length; + const tabTranslateValue = useSharedValue(0); + + // useCallBack with an empty array as input, which will call inner lambda only once and memoize the reference for future calls + const memoizedTabPressCallback = React.useCallback( + (index: number) => { + onChange(index); + }, + [onChange] + ); + useEffect(() => { + // If phone is set to RTL, make sure the animation does the correct transition. + const transitionMultiplier = isRTL ? -1 : 1; + tabTranslateValue.value = withSpring( + currentIndex * (translateValue * transitionMultiplier), + DEFAULT_SPRING_CONFIG + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentIndex]); + + const tabTranslateAnimatedStyles = useAnimatedStyle(() => { + return { + transform: [{ translateX: tabTranslateValue.value }], + }; + }); + return ( = ({ key={index} style={[styles.touchableContainer, pressableWrapper]} > - - - {segment} - - {badgeValues[index] && ( - - - {badgeValues[index]} - - - )} - + ); })}