@bigbinary/neetoui-rn 0.0.254 → 0.0.256
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +8 -12
- package/lib/components/LineLoader.js +1 -1
- package/lib/components/SegmentedTopBar/Indicator.js +1 -0
- package/lib/components/SegmentedTopBar/Tab.js +1 -0
- package/lib/components/SegmentedTopBar/index.js +1 -0
- package/package.json +1 -1
- package/src/components/LineLoader.jsx +1 -1
- package/src/components/SegmentedTopBar/Indicator.jsx +77 -0
- package/src/components/SegmentedTopBar/Tab.jsx +37 -0
- package/src/components/SegmentedTopBar/index.jsx +128 -0
- package/src/components/SegmentedTopBar.jsx +0 -211
package/index.d.ts
CHANGED
|
@@ -326,27 +326,27 @@ type ChatInputProps = {
|
|
|
326
326
|
onOptionChange?: (option: string) => void;
|
|
327
327
|
onChangeText: (text: string) => void;
|
|
328
328
|
onForward?: () => void;
|
|
329
|
-
onCannedResponse?:
|
|
329
|
+
onCannedResponse?: () => void;
|
|
330
330
|
toEmails?: string;
|
|
331
331
|
onReply?: () => void;
|
|
332
332
|
onAddNote?: () => void;
|
|
333
333
|
onAttachment?: () => void;
|
|
334
334
|
attachmentsCount?: number;
|
|
335
|
-
Attachments?:
|
|
335
|
+
Attachments?: React.FC;
|
|
336
336
|
showCannedResponsesFor?: Array<"REPLY" | "NOTE" | "FORWARD">;
|
|
337
337
|
showSuggestionsFor?: Array<"REPLY" | "NOTE" | "FORWARD">;
|
|
338
338
|
disabled?: boolean;
|
|
339
339
|
suggestions: Array<{
|
|
340
|
-
name: string
|
|
341
|
-
imageUrl: string
|
|
342
|
-
id: string
|
|
340
|
+
name: string;
|
|
341
|
+
imageUrl: string;
|
|
342
|
+
id: string;
|
|
343
343
|
}>;
|
|
344
344
|
};
|
|
345
345
|
|
|
346
346
|
type LineLoaderProps = {
|
|
347
|
-
backgroundColor?: string
|
|
348
|
-
foregroundColor?: string
|
|
349
|
-
height?: number
|
|
347
|
+
backgroundColor?: string;
|
|
348
|
+
foregroundColor?: string;
|
|
349
|
+
height?: number;
|
|
350
350
|
isLoading?: boolean;
|
|
351
351
|
};
|
|
352
352
|
|
|
@@ -526,10 +526,6 @@ interface NavigationProps {
|
|
|
526
526
|
}
|
|
527
527
|
interface SegmentedTopBarProps extends MaterialTopTabBarProps {
|
|
528
528
|
state?: SegmentedTopBarStateProps;
|
|
529
|
-
inactiveSegmentStyle?: ViewStyle;
|
|
530
|
-
activeSegmentStyle?: ViewStyle;
|
|
531
|
-
activeTextStyle?: TouchableProps;
|
|
532
|
-
inactiveTextStyle?: TouchableProps;
|
|
533
529
|
navigation?: NavigationProps;
|
|
534
530
|
height?: number;
|
|
535
531
|
descriptors?: object;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.LineLoader=void 0;var _react=_interopRequireDefault(require("react"));var _propTypes=_interopRequireDefault(require("prop-types"));var _native=_interopRequireWildcard(require("react-content-loader/native"));var _reactNativeSizeMatters=require("react-native-size-matters");var _theme=require("../theme");var _this=this,_jsxFileName="/home/runner/work/neeto-ui-rn/neeto-ui-rn/src/components/LineLoader.jsx";function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}var LineLoader=function LineLoader(_ref){var isLoading=_ref.isLoading,_ref$backgroundColor=_ref.backgroundColor,backgroundColor=_ref$backgroundColor===void 0?_theme.theme.colors.background.primary:_ref$backgroundColor,_ref$foregroundColor=_ref.foregroundColor,foregroundColor=_ref$foregroundColor===void 0?_theme.theme.colors.background.base:_ref$foregroundColor,_ref$height=_ref.height,height=_ref$height===void 0?(0,_reactNativeSizeMatters.moderateScale)(
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.LineLoader=void 0;var _react=_interopRequireDefault(require("react"));var _propTypes=_interopRequireDefault(require("prop-types"));var _native=_interopRequireWildcard(require("react-content-loader/native"));var _reactNativeSizeMatters=require("react-native-size-matters");var _theme=require("../theme");var _this=this,_jsxFileName="/home/runner/work/neeto-ui-rn/neeto-ui-rn/src/components/LineLoader.jsx";function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}var LineLoader=function LineLoader(_ref){var isLoading=_ref.isLoading,_ref$backgroundColor=_ref.backgroundColor,backgroundColor=_ref$backgroundColor===void 0?_theme.theme.colors.background.primary:_ref$backgroundColor,_ref$foregroundColor=_ref.foregroundColor,foregroundColor=_ref$foregroundColor===void 0?_theme.theme.colors.background.base:_ref$foregroundColor,_ref$height=_ref.height,height=_ref$height===void 0?(0,_reactNativeSizeMatters.moderateScale)(3):_ref$height;return _react.default.createElement(_native.default,{animate:isLoading,backgroundColor:backgroundColor,foregroundColor:foregroundColor,height:height,interval:0,key:isLoading,speed:1,width:"100%",__self:_this,__source:{fileName:_jsxFileName,lineNumber:15,columnNumber:3}},_react.default.createElement(_native.Rect,{height:height,width:"100%",x:0,y:0,__self:_this,__source:{fileName:_jsxFileName,lineNumber:25,columnNumber:5}}));};exports.LineLoader=LineLoader;LineLoader.propTypes={isLoading:_propTypes.default.bool,backgroundColor:_propTypes.default.string,foregroundColor:_propTypes.default.string,height:_propTypes.default.number};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.Indicator=void 0;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _propTypes=_interopRequireDefault(require("prop-types"));var _reactNativeReanimated=_interopRequireWildcard(require("react-native-reanimated"));var _reactNativeSizeMatters=require("react-native-size-matters");var _theme=require("../../theme");var _this=this,_jsxFileName="/home/runner/work/neeto-ui-rn/neeto-ui-rn/src/components/SegmentedTopBar/Indicator.jsx";function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}var springConfig={mass:1,overshootClamping:true,restSpeedThreshold:0.5,restDisplacementThreshold:0.5};var spacing=(0,_reactNativeSizeMatters.moderateScale)(6);var Indicator=function Indicator(_ref){var measure=_ref.measure;var x=measure.x,width=measure.width,height=measure.height;var translateX=(0,_reactNativeReanimated.useSharedValue)(0);var animatedWidth=(0,_reactNativeReanimated.useSharedValue)(0);(0,_react.useEffect)(function(){(0,_reactNativeReanimated.cancelAnimation)(translateX);(0,_reactNativeReanimated.cancelAnimation)(animatedWidth);translateX.value=(0,_reactNativeReanimated.withSpring)(x+spacing/2,springConfig);animatedWidth.value=(0,_reactNativeReanimated.withSpring)(width-spacing,springConfig);},[animatedWidth,translateX,width,x]);var tabTranslateAnimatedStyles=(0,_reactNativeReanimated.useAnimatedStyle)(function(){var _f=function _f(){return{transform:[{translateX:translateX.value}],width:animatedWidth.value};};_f._closure={translateX:translateX,animatedWidth:animatedWidth};_f.asString="function _f(){const{translateX,animatedWidth}=jsThis._closure;{return{transform:[{translateX:translateX.value}],width:animatedWidth.value};}}";_f.__workletHash=12388547266078;_f.__location="/home/runner/work/neeto-ui-rn/neeto-ui-rn/src/components/SegmentedTopBar/Indicator.jsx (38:54)";_f.__optimalization=3;return _f;}());return _react.default.createElement(_reactNativeReanimated.default.View,{style:[styles.movingSegmentStyle,{height:height-spacing},tabTranslateAnimatedStyles],__self:_this,__source:{fileName:_jsxFileName,lineNumber:44,columnNumber:5}});};exports.Indicator=Indicator;var styles=_reactNative.StyleSheet.create({movingSegmentStyle:{position:"absolute",top:spacing/2,borderRadius:(0,_reactNativeSizeMatters.moderateScale)(6),backgroundColor:_theme.theme.colors.background.primary,shadowColor:_theme.theme.colors.background.grey,shadowOffset:{width:0,height:5},shadowOpacity:0.34,shadowRadius:6.27,elevation:10}});Indicator.propTypes={measure:_propTypes.default.shape({x:_propTypes.default.number.isRequired,width:_propTypes.default.number.isRequired,height:_propTypes.default.number.isRequired}).isRequired};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.Tab=void 0;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _propTypes=_interopRequireDefault(require("prop-types"));var _=require("./..");var _this=this,_jsxFileName="/home/runner/work/neeto-ui-rn/neeto-ui-rn/src/components/SegmentedTopBar/Tab.jsx";function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}var Tab=(0,_react.forwardRef)(function(_ref,ref){var label=_ref.label,value=_ref.value,navigation=_ref.navigation,flex=_ref.flex;var handleOnPress=(0,_react.useCallback)(function(){return navigation.navigate(value);},[navigation,value]);return _react.default.createElement(_reactNative.View,{ref:ref,style:{flex:flex},__self:_this,__source:{fileName:_jsxFileName,lineNumber:15,columnNumber:5}},_react.default.createElement(_.Touchable,{flex:1,justifyContent:"center",onPress:handleOnPress,__self:_this,__source:{fileName:_jsxFileName,lineNumber:16,columnNumber:7}},_react.default.createElement(_.Typography,{fontFamily:"sf500",fontSize:"xs",numberOfLines:1,textAlign:"center",__self:_this,__source:{fileName:_jsxFileName,lineNumber:17,columnNumber:9}},label)));});exports.Tab=Tab;Tab.displayName="Tab";Tab.propTypes={flex:_propTypes.default.number,label:_propTypes.default.string.isRequired,value:_propTypes.default.string.isRequired,navigation:_propTypes.default.object};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:true});exports.SegmentedTopBar=void 0;var _slicedToArray2=_interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _propTypes=_interopRequireDefault(require("prop-types"));var _reactNativeSizeMatters=require("react-native-size-matters");var _theme=require("../../theme");var _Indicator=require("./Indicator");var _Tab=require("./Tab");var _this=this,_jsxFileName="/home/runner/work/neeto-ui-rn/neeto-ui-rn/src/components/SegmentedTopBar/index.jsx";function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function _getRequireWildcardCache(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}var SegmentedTopBar=function SegmentedTopBar(_ref){var _ref$state=_ref.state,routes=_ref$state.routes,index=_ref$state.index,navigation=_ref.navigation,height=_ref.height,descriptors=_ref.descriptors;var containerRef=(0,_react.useRef)();var _useState=(0,_react.useState)([]),_useState2=(0,_slicedToArray2.default)(_useState,2),measures=_useState2[0],setMeasures=_useState2[1];var tabsData=(0,_react.useMemo)(function(){return routes.map(function(_ref2){var _ref3,_options$tabBarLabel;var key=_ref2.key,name=_ref2.name;var options=descriptors[key].options;var label=(_ref3=(_options$tabBarLabel=options.tabBarLabel)!=null?_options$tabBarLabel:options.title)!=null?_ref3:name;return{label:label,value:name,ref:(0,_react.createRef)()};});},[]);(0,_react.useLayoutEffect)(function(){var _measures=[];tabsData.forEach(function(_ref4){var ref=_ref4.ref;ref.current.measureLayout(containerRef.current,function(x,y,width,height){_measures.push({x:x,y:y,width:width,height:height});if(_measures.length===tabsData.length){setMeasures(_measures);}});});},[measures.length]);return _react.default.createElement(_reactNative.View,{height:height,ref:containerRef,style:styles.container,__self:_this,__source:{fileName:_jsxFileName,lineNumber:94,columnNumber:5}},measures.length>0&&_react.default.createElement(_Indicator.Indicator,{measure:measures[index],__self:_this,__source:{fileName:_jsxFileName,lineNumber:95,columnNumber:31}}),tabsData.map(function(_ref5){var label=_ref5.label,value=_ref5.value,ref=_ref5.ref;return _react.default.createElement(_Tab.Tab,{flex:tabsData.length>3?label.length:1,key:value,label:label,navigation:navigation,ref:ref,value:value,__self:_this,__source:{fileName:_jsxFileName,lineNumber:97,columnNumber:9}});}));};exports.SegmentedTopBar=SegmentedTopBar;var styles=_reactNative.StyleSheet.create({container:{flexDirection:"row",borderRadius:(0,_reactNativeSizeMatters.moderateScale)(6),backgroundColor:_theme.theme.colors.background.secondary}});SegmentedTopBar.propTypes={state:_propTypes.default.object,height:_propTypes.default.number,navigation:_propTypes.default.object,descriptors:_propTypes.default.object};SegmentedTopBar.defaultProps={tabs:[],height:(0,_reactNativeSizeMatters.moderateScale)(36)};
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ export const LineLoader = ({
|
|
|
10
10
|
isLoading,
|
|
11
11
|
backgroundColor = theme.colors.background.primary,
|
|
12
12
|
foregroundColor = theme.colors.background.base,
|
|
13
|
-
height = moderateScale(
|
|
13
|
+
height = moderateScale(3),
|
|
14
14
|
}) => (
|
|
15
15
|
<ContentLoader
|
|
16
16
|
animate={isLoading}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import { StyleSheet } from "react-native";
|
|
3
|
+
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
import Animated, {
|
|
6
|
+
cancelAnimation,
|
|
7
|
+
useAnimatedStyle,
|
|
8
|
+
useSharedValue,
|
|
9
|
+
withSpring,
|
|
10
|
+
} from "react-native-reanimated";
|
|
11
|
+
import { moderateScale } from "react-native-size-matters";
|
|
12
|
+
|
|
13
|
+
import { theme } from "@theme";
|
|
14
|
+
|
|
15
|
+
const springConfig = {
|
|
16
|
+
mass: 1,
|
|
17
|
+
overshootClamping: true,
|
|
18
|
+
restSpeedThreshold: 0.5,
|
|
19
|
+
restDisplacementThreshold: 0.5,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const spacing = moderateScale(6);
|
|
23
|
+
|
|
24
|
+
export const Indicator = ({ measure }) => {
|
|
25
|
+
const { x, width, height } = measure;
|
|
26
|
+
|
|
27
|
+
const translateX = useSharedValue(0);
|
|
28
|
+
const animatedWidth = useSharedValue(0);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
cancelAnimation(translateX);
|
|
32
|
+
cancelAnimation(animatedWidth);
|
|
33
|
+
|
|
34
|
+
translateX.value = withSpring(x + spacing / 2, springConfig);
|
|
35
|
+
animatedWidth.value = withSpring(width - spacing, springConfig);
|
|
36
|
+
}, [animatedWidth, translateX, width, x]);
|
|
37
|
+
|
|
38
|
+
const tabTranslateAnimatedStyles = useAnimatedStyle(() => ({
|
|
39
|
+
transform: [{ translateX: translateX.value }],
|
|
40
|
+
width: animatedWidth.value,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Animated.View
|
|
45
|
+
style={[
|
|
46
|
+
styles.movingSegmentStyle,
|
|
47
|
+
{ height: height - spacing },
|
|
48
|
+
tabTranslateAnimatedStyles,
|
|
49
|
+
]}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const styles = StyleSheet.create({
|
|
55
|
+
movingSegmentStyle: {
|
|
56
|
+
position: "absolute",
|
|
57
|
+
top: spacing / 2,
|
|
58
|
+
borderRadius: moderateScale(6),
|
|
59
|
+
backgroundColor: theme.colors.background.primary,
|
|
60
|
+
shadowColor: theme.colors.background.grey,
|
|
61
|
+
shadowOffset: {
|
|
62
|
+
width: 0,
|
|
63
|
+
height: 5,
|
|
64
|
+
},
|
|
65
|
+
shadowOpacity: 0.34,
|
|
66
|
+
shadowRadius: 6.27,
|
|
67
|
+
elevation: 10,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
Indicator.propTypes = {
|
|
72
|
+
measure: PropTypes.shape({
|
|
73
|
+
x: PropTypes.number.isRequired,
|
|
74
|
+
width: PropTypes.number.isRequired,
|
|
75
|
+
height: PropTypes.number.isRequired,
|
|
76
|
+
}).isRequired,
|
|
77
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback } from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
import { Typography, Touchable } from "@components";
|
|
7
|
+
|
|
8
|
+
export const Tab = forwardRef(({ label, value, navigation, flex }, ref) => {
|
|
9
|
+
const handleOnPress = useCallback(
|
|
10
|
+
() => navigation.navigate(value),
|
|
11
|
+
[navigation, value]
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<View ref={ref} style={{ flex }}>
|
|
16
|
+
<Touchable flex={1} justifyContent="center" onPress={handleOnPress}>
|
|
17
|
+
<Typography
|
|
18
|
+
fontFamily="sf500"
|
|
19
|
+
fontSize="xs"
|
|
20
|
+
numberOfLines={1}
|
|
21
|
+
textAlign="center"
|
|
22
|
+
>
|
|
23
|
+
{label}
|
|
24
|
+
</Typography>
|
|
25
|
+
</Touchable>
|
|
26
|
+
</View>
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
Tab.displayName = "Tab";
|
|
31
|
+
|
|
32
|
+
Tab.propTypes = {
|
|
33
|
+
flex: PropTypes.number,
|
|
34
|
+
label: PropTypes.string.isRequired,
|
|
35
|
+
value: PropTypes.string.isRequired,
|
|
36
|
+
navigation: PropTypes.object,
|
|
37
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createRef,
|
|
3
|
+
useState,
|
|
4
|
+
useMemo,
|
|
5
|
+
useRef,
|
|
6
|
+
useLayoutEffect,
|
|
7
|
+
} from "react";
|
|
8
|
+
import { StyleSheet, View } from "react-native";
|
|
9
|
+
|
|
10
|
+
import PropTypes from "prop-types";
|
|
11
|
+
import { moderateScale } from "react-native-size-matters";
|
|
12
|
+
|
|
13
|
+
import { theme } from "@theme";
|
|
14
|
+
|
|
15
|
+
import { Indicator } from "./Indicator";
|
|
16
|
+
import { Tab } from "./Tab";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* A Segment Picker component that provides toggling between two or more views.
|
|
21
|
+
*
|
|
22
|
+
* <div class="screenshots">
|
|
23
|
+
* <img src="screenshots/toptabbar/toptabbar-1.png" />
|
|
24
|
+
* <img src="screenshots/toptabbar/toptabbar-2.png" />
|
|
25
|
+
* </div>
|
|
26
|
+
*
|
|
27
|
+
* ## Usage
|
|
28
|
+
* ```js
|
|
29
|
+
* import * as React from 'react';
|
|
30
|
+
* import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs";
|
|
31
|
+
* import { NavigationContainer } from "@react-navigation/native";
|
|
32
|
+
*
|
|
33
|
+
* import { SegmentedTopBar } from '@bigbinary/neetoui-rn';
|
|
34
|
+
*
|
|
35
|
+
* const Tab = createMaterialTopTabNavigator();
|
|
36
|
+
*
|
|
37
|
+
* export default function Main(){
|
|
38
|
+
*
|
|
39
|
+
* return (
|
|
40
|
+
* <NavigationContainer>
|
|
41
|
+
* <Tab.Navigator tabBar={props => <SegmentedTopBar {...props} />} >
|
|
42
|
+
* <Tab.Screen
|
|
43
|
+
* name="Home"
|
|
44
|
+
* component={HomeScreen}
|
|
45
|
+
* />
|
|
46
|
+
*
|
|
47
|
+
* <Tab.Screen
|
|
48
|
+
* name="Settings"
|
|
49
|
+
* component={SettingsScreen}
|
|
50
|
+
* />
|
|
51
|
+
* </Tab.Navigator>
|
|
52
|
+
* </NavigationContainer>
|
|
53
|
+
* );
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
export const SegmentedTopBar = ({
|
|
59
|
+
state: { routes, index },
|
|
60
|
+
navigation,
|
|
61
|
+
height,
|
|
62
|
+
descriptors,
|
|
63
|
+
}) => {
|
|
64
|
+
const containerRef = useRef();
|
|
65
|
+
|
|
66
|
+
const [measures, setMeasures] = useState([]);
|
|
67
|
+
|
|
68
|
+
const tabsData = useMemo(
|
|
69
|
+
() =>
|
|
70
|
+
routes.map(({ key, name }) => {
|
|
71
|
+
const { options } = descriptors[key];
|
|
72
|
+
const label = options.tabBarLabel ?? options.title ?? name;
|
|
73
|
+
|
|
74
|
+
return { label, value: name, ref: createRef() };
|
|
75
|
+
}),
|
|
76
|
+
[]
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
useLayoutEffect(() => {
|
|
80
|
+
const _measures = [];
|
|
81
|
+
|
|
82
|
+
tabsData.forEach(({ ref }) => {
|
|
83
|
+
ref.current.measureLayout(containerRef.current, (x, y, width, height) => {
|
|
84
|
+
_measures.push({ x, y, width, height });
|
|
85
|
+
|
|
86
|
+
if (_measures.length === tabsData.length) {
|
|
87
|
+
setMeasures(_measures);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}, [measures.length]);
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<View height={height} ref={containerRef} style={styles.container}>
|
|
95
|
+
{measures.length > 0 && <Indicator measure={measures[index]} />}
|
|
96
|
+
{tabsData.map(({ label, value, ref }) => (
|
|
97
|
+
<Tab
|
|
98
|
+
flex={tabsData.length > 3 ? label.length : 1}
|
|
99
|
+
key={value}
|
|
100
|
+
label={label}
|
|
101
|
+
navigation={navigation}
|
|
102
|
+
ref={ref}
|
|
103
|
+
value={value}
|
|
104
|
+
/>
|
|
105
|
+
))}
|
|
106
|
+
</View>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const styles = StyleSheet.create({
|
|
111
|
+
container: {
|
|
112
|
+
flexDirection: "row",
|
|
113
|
+
borderRadius: moderateScale(6),
|
|
114
|
+
backgroundColor: theme.colors.background.secondary,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
SegmentedTopBar.propTypes = {
|
|
119
|
+
state: PropTypes.object,
|
|
120
|
+
height: PropTypes.number,
|
|
121
|
+
navigation: PropTypes.object,
|
|
122
|
+
descriptors: PropTypes.object,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
SegmentedTopBar.defaultProps = {
|
|
126
|
+
tabs: [],
|
|
127
|
+
height: moderateScale(36),
|
|
128
|
+
};
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
2
|
-
import { Dimensions, Platform, StyleSheet } from "react-native";
|
|
3
|
-
|
|
4
|
-
import PropTypes from "prop-types";
|
|
5
|
-
import Animated, {
|
|
6
|
-
useAnimatedStyle,
|
|
7
|
-
useSharedValue,
|
|
8
|
-
withSpring,
|
|
9
|
-
} from "react-native-reanimated";
|
|
10
|
-
import { moderateScale } from "react-native-size-matters";
|
|
11
|
-
|
|
12
|
-
import { Typography, Touchable } from "@components";
|
|
13
|
-
import { theme } from "@theme";
|
|
14
|
-
|
|
15
|
-
const defaultShadowStyle = {
|
|
16
|
-
shadowColor: theme.colors.background.grey800,
|
|
17
|
-
shadowOffset: {
|
|
18
|
-
width: 0,
|
|
19
|
-
height: moderateScale(2),
|
|
20
|
-
},
|
|
21
|
-
shadowOpacity: 0.23,
|
|
22
|
-
shadowRadius: moderateScale(2.62),
|
|
23
|
-
elevation: 4,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// eslint-disable-next-line @bigbinary/neeto/no-dangling-constants
|
|
27
|
-
const DEFAULT_SPRING_CONFIG = {
|
|
28
|
-
stiffness: 150,
|
|
29
|
-
damping: 20,
|
|
30
|
-
mass: 1,
|
|
31
|
-
overshootClamping: false,
|
|
32
|
-
restSpeedThreshold: 0.001,
|
|
33
|
-
restDisplacementThreshold: 0.001,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// So that it stretches in landscape mode.
|
|
37
|
-
const width = Dimensions.get("screen").width - moderateScale(32);
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
*
|
|
41
|
-
* A Segment Picker component that provides toggling between two or more views.
|
|
42
|
-
*
|
|
43
|
-
* <div class="screenshots">
|
|
44
|
-
* <img src="screenshots/toptabbar/toptabbar-1.png" />
|
|
45
|
-
* <img src="screenshots/toptabbar/toptabbar-2.png" />
|
|
46
|
-
* </div>
|
|
47
|
-
*
|
|
48
|
-
* ## Usage
|
|
49
|
-
* ```js
|
|
50
|
-
* import * as React from 'react';
|
|
51
|
-
* import { createMaterialTopTabNavigator } from "@react-navigation/material-top-tabs";
|
|
52
|
-
* import { NavigationContainer } from "@react-navigation/native";
|
|
53
|
-
*
|
|
54
|
-
* import { SegmentedTopBar } from '@bigbinary/neetoui-rn';
|
|
55
|
-
*
|
|
56
|
-
* const Tab = createMaterialTopTabNavigator();
|
|
57
|
-
*
|
|
58
|
-
* export default function Main(){
|
|
59
|
-
*
|
|
60
|
-
* return (
|
|
61
|
-
* <NavigationContainer>
|
|
62
|
-
* <Tab.Navigator tabBar={props => <SegmentedTopBar {...props} />} >
|
|
63
|
-
* <Tab.Screen
|
|
64
|
-
* name="Home"
|
|
65
|
-
* component={HomeScreen}
|
|
66
|
-
* />
|
|
67
|
-
*
|
|
68
|
-
* <Tab.Screen
|
|
69
|
-
* name="Settings"
|
|
70
|
-
* component={SettingsScreen}
|
|
71
|
-
* />
|
|
72
|
-
* </Tab.Navigator>
|
|
73
|
-
* </NavigationContainer>
|
|
74
|
-
* );
|
|
75
|
-
* }
|
|
76
|
-
* ```
|
|
77
|
-
*/
|
|
78
|
-
|
|
79
|
-
export const SegmentedTopBar = ({
|
|
80
|
-
state: { routes, index },
|
|
81
|
-
inactiveSegmentStyle,
|
|
82
|
-
activeSegmentStyle,
|
|
83
|
-
activeTextStyle,
|
|
84
|
-
inactiveTextStyle,
|
|
85
|
-
navigation,
|
|
86
|
-
height,
|
|
87
|
-
descriptors,
|
|
88
|
-
}) => {
|
|
89
|
-
const translateValue = (width - 4) / routes?.length;
|
|
90
|
-
const tabTranslateValue = useSharedValue(0);
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
tabTranslateValue.value = withSpring(
|
|
93
|
-
index * Number(translateValue),
|
|
94
|
-
DEFAULT_SPRING_CONFIG
|
|
95
|
-
);
|
|
96
|
-
}, [index]);
|
|
97
|
-
|
|
98
|
-
const tabTranslateAnimatedStyles = useAnimatedStyle(() => ({
|
|
99
|
-
transform: [{ translateX: tabTranslateValue.value }],
|
|
100
|
-
}));
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<Animated.View
|
|
104
|
-
style={[styles.defaultSegmentedControlWrapper, inactiveSegmentStyle]}
|
|
105
|
-
>
|
|
106
|
-
<Animated.View
|
|
107
|
-
style={[
|
|
108
|
-
styles.movingSegmentStyle,
|
|
109
|
-
activeSegmentStyle,
|
|
110
|
-
defaultShadowStyle,
|
|
111
|
-
StyleSheet.absoluteFill,
|
|
112
|
-
{
|
|
113
|
-
width: (width - moderateScale(4)) / routes?.length,
|
|
114
|
-
},
|
|
115
|
-
tabTranslateAnimatedStyles,
|
|
116
|
-
]}
|
|
117
|
-
/>
|
|
118
|
-
{routes.map((route, i) => {
|
|
119
|
-
const currentIndexTextStyle =
|
|
120
|
-
index === index + 1 ? activeTextStyle : inactiveTextStyle;
|
|
121
|
-
const { options } = descriptors[route.key];
|
|
122
|
-
const label =
|
|
123
|
-
options.tabBarLabel !== undefined
|
|
124
|
-
? options.tabBarLabel
|
|
125
|
-
: options.title !== undefined
|
|
126
|
-
? options.title
|
|
127
|
-
: route.name;
|
|
128
|
-
|
|
129
|
-
return (
|
|
130
|
-
<Touchable
|
|
131
|
-
alignItems="center"
|
|
132
|
-
elevation={Platform.OS === "android" ? 9 : null}
|
|
133
|
-
flex={1}
|
|
134
|
-
height={height}
|
|
135
|
-
justifyContent="center"
|
|
136
|
-
key={i}
|
|
137
|
-
onPress={() => navigation.navigate(route.name)}
|
|
138
|
-
{...currentIndexTextStyle}
|
|
139
|
-
>
|
|
140
|
-
<Typography
|
|
141
|
-
color="font.grey800"
|
|
142
|
-
fontFamily="sf500"
|
|
143
|
-
fontSize="xs"
|
|
144
|
-
textAlign="center"
|
|
145
|
-
>
|
|
146
|
-
{label}
|
|
147
|
-
</Typography>
|
|
148
|
-
</Touchable>
|
|
149
|
-
);
|
|
150
|
-
})}
|
|
151
|
-
</Animated.View>
|
|
152
|
-
);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const styles = StyleSheet.create({
|
|
156
|
-
segmentedControlWrapper: {
|
|
157
|
-
display: "flex",
|
|
158
|
-
flexDirection: "row",
|
|
159
|
-
alignItems: "center",
|
|
160
|
-
borderRadius: moderateScale(8),
|
|
161
|
-
width,
|
|
162
|
-
},
|
|
163
|
-
defaultSegmentedControlWrapper: {
|
|
164
|
-
position: "relative",
|
|
165
|
-
display: "flex",
|
|
166
|
-
flexDirection: "row",
|
|
167
|
-
alignItems: "center",
|
|
168
|
-
borderRadius: moderateScale(8),
|
|
169
|
-
backgroundColor: "#F6F6FA",
|
|
170
|
-
width,
|
|
171
|
-
marginBottom: moderateScale(5),
|
|
172
|
-
},
|
|
173
|
-
movingSegmentStyle: {
|
|
174
|
-
top: 0,
|
|
175
|
-
marginVertical: moderateScale(2),
|
|
176
|
-
marginHorizontal: moderateScale(2),
|
|
177
|
-
borderRadius: moderateScale(6),
|
|
178
|
-
backgroundColor: "#FFFFFF",
|
|
179
|
-
},
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
SegmentedTopBar.propTypes = {
|
|
183
|
-
/**
|
|
184
|
-
* Navigation routes and additional data.
|
|
185
|
-
*/
|
|
186
|
-
state: PropTypes.object,
|
|
187
|
-
/**
|
|
188
|
-
* To change the inactive segment container style.
|
|
189
|
-
*/
|
|
190
|
-
inactiveSegmentStyle: PropTypes.object,
|
|
191
|
-
/**
|
|
192
|
-
* To change the active segment container style.
|
|
193
|
-
*/
|
|
194
|
-
activeSegmentStyle: PropTypes.object,
|
|
195
|
-
/**
|
|
196
|
-
* To change the inactive segment font style.
|
|
197
|
-
*/
|
|
198
|
-
inactiveTextStyle: PropTypes.object,
|
|
199
|
-
/**
|
|
200
|
-
* To change the active segment font style.
|
|
201
|
-
*/
|
|
202
|
-
activeTextStyle: PropTypes.object,
|
|
203
|
-
height: PropTypes.number,
|
|
204
|
-
navigation: PropTypes.object,
|
|
205
|
-
descriptors: PropTypes.object,
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
SegmentedTopBar.defaultProps = {
|
|
209
|
-
tabs: [],
|
|
210
|
-
height: moderateScale(32),
|
|
211
|
-
};
|