|
@@ -4,14 +4,17 @@ import {
|
|
|
forwardRef,
|
|
forwardRef,
|
|
|
useEffect,
|
|
useEffect,
|
|
|
useState,
|
|
useState,
|
|
|
|
|
+ Fragment,
|
|
|
useRef
|
|
useRef
|
|
|
} from "react";
|
|
} from "react";
|
|
|
import {
|
|
import {
|
|
|
|
|
+ Platform,
|
|
|
Animated,
|
|
Animated,
|
|
|
Easing,
|
|
Easing,
|
|
|
View
|
|
View
|
|
|
} from "react-native";
|
|
} from "react-native";
|
|
|
import type {
|
|
import type {
|
|
|
|
|
+ MenuButton,
|
|
|
IMenuRef
|
|
IMenuRef
|
|
|
} from "./type";
|
|
} from "./type";
|
|
|
import type IMenuProps from "./type";
|
|
import type IMenuProps from "./type";
|
|
@@ -24,21 +27,39 @@ import {
|
|
|
import type {
|
|
import type {
|
|
|
RefForwardingComponent
|
|
RefForwardingComponent
|
|
|
} from "../../types";
|
|
} from "../../types";
|
|
|
-import Modal from "../modal";
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ ChevronRight as ChevronRightIcon,
|
|
|
|
|
+ ChevronLeft as ChevronLeftIcon,
|
|
|
|
|
+ ChevronDown as ChevronDownIcon
|
|
|
|
|
+} from "lucide-react-native";
|
|
|
|
|
+import {
|
|
|
|
|
+ SafeAreaView
|
|
|
|
|
+} from "react-native-safe-area-context";
|
|
|
import {
|
|
import {
|
|
|
Portal
|
|
Portal
|
|
|
} from "../../helpers/portalize";
|
|
} from "../../helpers/portalize";
|
|
|
|
|
+import Seperator from "../seperator";
|
|
|
|
|
+import SiteLogo from "../siteLogo";
|
|
|
|
|
+import RowCard from "../rowCard";
|
|
|
|
|
+import Modal from "../modal";
|
|
|
|
|
|
|
|
const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
- portalName = "menu-system",
|
|
|
|
|
|
|
+ isWorkWithSafeAreaView = true,
|
|
|
isWorkWithAnimation = true,
|
|
isWorkWithAnimation = true,
|
|
|
|
|
+ renderHeader: RenderHeader,
|
|
|
|
|
+ renderFooter: RenderFooter,
|
|
|
|
|
+ portalName = "menu-system",
|
|
|
isWorkWithPortal = true,
|
|
isWorkWithPortal = true,
|
|
|
isWorkWithModal = true,
|
|
isWorkWithModal = true,
|
|
|
|
|
+ close: closeAction,
|
|
|
|
|
+ siteLogoProps,
|
|
|
customTheme,
|
|
customTheme,
|
|
|
|
|
+ navigation,
|
|
|
modalProps,
|
|
modalProps,
|
|
|
isCollabs,
|
|
isCollabs,
|
|
|
onClosed,
|
|
onClosed,
|
|
|
onOpened,
|
|
onOpened,
|
|
|
|
|
+ buttons,
|
|
|
onClose,
|
|
onClose,
|
|
|
onOpen,
|
|
onOpen,
|
|
|
style,
|
|
style,
|
|
@@ -51,6 +72,8 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
} = NCoreUIKitTheme.useContext(customTheme);
|
|
} = NCoreUIKitTheme.useContext(customTheme);
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
|
|
+ headerContainer: headerContainerDynamicStyle,
|
|
|
|
|
+ seperator: seperatorDynamicStyle,
|
|
|
container: containerDynamicStyle
|
|
container: containerDynamicStyle
|
|
|
} = useStyles({
|
|
} = useStyles({
|
|
|
colors,
|
|
colors,
|
|
@@ -70,10 +93,10 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
const [
|
|
const [
|
|
|
isActive,
|
|
isActive,
|
|
|
setIsActive
|
|
setIsActive
|
|
|
- ] = useState(measures === null ? true : isCollabs);
|
|
|
|
|
|
|
+ ] = useState(false);
|
|
|
|
|
|
|
|
const animatedX = useRef(new Animated.Value(0)).current;
|
|
const animatedX = useRef(new Animated.Value(0)).current;
|
|
|
- console.log("aha da ranza:", id);
|
|
|
|
|
|
|
+
|
|
|
useImperativeHandle(
|
|
useImperativeHandle(
|
|
|
ref,
|
|
ref,
|
|
|
() => ({
|
|
() => ({
|
|
@@ -84,19 +107,17 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
- console.log("z", new Date().toISOString());
|
|
|
|
|
if(measures !== null) {
|
|
if(measures !== null) {
|
|
|
animatedX.setValue(measures * -1);
|
|
animatedX.setValue(measures * -1);
|
|
|
|
|
|
|
|
if(!isOpacityVisible) setIsOpacityVisible(true);
|
|
if(!isOpacityVisible) setIsOpacityVisible(true);
|
|
|
- console.log("x", new Date().toISOString());
|
|
|
|
|
|
|
+
|
|
|
if(isActive) setIsActive(false);
|
|
if(isActive) setIsActive(false);
|
|
|
}
|
|
}
|
|
|
}, [measures]);
|
|
}, [measures]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
- console.log("y", new Date().toISOString(), isCollabs);
|
|
|
|
|
- setIsActive(isCollabs);
|
|
|
|
|
|
|
+ if(isCollabs !== undefined) setIsActive(isCollabs);
|
|
|
}, [isCollabs]);
|
|
}, [isCollabs]);
|
|
|
|
|
|
|
|
useLayoutEffect(() => {
|
|
useLayoutEffect(() => {
|
|
@@ -162,7 +183,7 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
Animated.timing(animatedX, {
|
|
Animated.timing(animatedX, {
|
|
|
- useNativeDriver: true,
|
|
|
|
|
|
|
+ useNativeDriver: Platform.OS !== "web",
|
|
|
easing: Easing.linear,
|
|
easing: Easing.linear,
|
|
|
duration: 300,
|
|
duration: 300,
|
|
|
toValue: 0
|
|
toValue: 0
|
|
@@ -183,8 +204,8 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
Animated.timing(animatedX, {
|
|
Animated.timing(animatedX, {
|
|
|
|
|
+ useNativeDriver: Platform.OS !== "web",
|
|
|
toValue: measures! * -1,
|
|
toValue: measures! * -1,
|
|
|
- useNativeDriver: true,
|
|
|
|
|
easing: Easing.linear,
|
|
easing: Easing.linear,
|
|
|
duration: 300
|
|
duration: 300
|
|
|
}).start(({
|
|
}).start(({
|
|
@@ -198,6 +219,207 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const renderHeader = () => {
|
|
|
|
|
+ if(RenderHeader) {
|
|
|
|
|
+ return <RenderHeader/>;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.headerContainer,
|
|
|
|
|
+ headerContainerDynamicStyle
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ <SiteLogo
|
|
|
|
|
+ {...siteLogoProps}
|
|
|
|
|
+ />
|
|
|
|
|
+ <Seperator
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.seperator,
|
|
|
|
|
+ seperatorDynamicStyle
|
|
|
|
|
+ ]}
|
|
|
|
|
+ />
|
|
|
|
|
+ </View>;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const isPageActive = ((buttonItem: MenuButton) => {
|
|
|
|
|
+ const state = navigation.getState();
|
|
|
|
|
+ const currentRoute = state?.routes?.[state.index];
|
|
|
|
|
+
|
|
|
|
|
+ if(!currentRoute) return false;
|
|
|
|
|
+
|
|
|
|
|
+ if(currentRoute.state) {
|
|
|
|
|
+ const nestedRoute = currentRoute.state.routes?.[currentRoute.state.index];
|
|
|
|
|
+ return nestedRoute?.name === (buttonItem.redirectSub ?? buttonItem.redirectMain);
|
|
|
|
|
+ } else if(currentRoute.name) {
|
|
|
|
|
+ return currentRoute.name === (buttonItem.redirectSub ?? buttonItem.redirectMain);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return currentRoute.name === (buttonItem.redirectSub ?? buttonItem.redirectMain);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const renderMenuButton = (buttonItem: MenuButton, buttonIndex: number) => {
|
|
|
|
|
+ const [
|
|
|
|
|
+ isCollabs,
|
|
|
|
|
+ setIsCollabs
|
|
|
|
|
+ ] = useState(buttonItem.isCollabs);
|
|
|
|
|
+
|
|
|
|
|
+ const [
|
|
|
|
|
+ measure,
|
|
|
|
|
+ setMeasure
|
|
|
|
|
+ ] = useState<null | number>(null);
|
|
|
|
|
+
|
|
|
|
|
+ const [
|
|
|
|
|
+ isPActive,
|
|
|
|
|
+ setIsPActive
|
|
|
|
|
+ ] = useState(isPageActive(buttonItem));
|
|
|
|
|
+
|
|
|
|
|
+ const animatedCollabs = useRef(new Animated.Value(0)).current;
|
|
|
|
|
+
|
|
|
|
|
+ if(buttonItem.isCollabsable) {
|
|
|
|
|
+ useLayoutEffect(() => {
|
|
|
|
|
+ if(measure === null) return;
|
|
|
|
|
+
|
|
|
|
|
+ if(isCollabs) {
|
|
|
|
|
+ Animated.timing(animatedCollabs, {
|
|
|
|
|
+ useNativeDriver: Platform.OS !== "web",
|
|
|
|
|
+ toValue: Number(measure),
|
|
|
|
|
+ easing: Easing.linear,
|
|
|
|
|
+ duration: 150
|
|
|
|
|
+ }).start();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Animated.timing(animatedCollabs, {
|
|
|
|
|
+ useNativeDriver: Platform.OS !== "web",
|
|
|
|
|
+ easing: Easing.linear,
|
|
|
|
|
+ duration: 150,
|
|
|
|
|
+ toValue: 0
|
|
|
|
|
+ }).start();
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [isCollabs]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return <View
|
|
|
|
|
+ key={`menu-button-${id}-${buttonIndex}`}
|
|
|
|
|
+ >
|
|
|
|
|
+ <RowCard
|
|
|
|
|
+ {...buttonItem.props}
|
|
|
|
|
+ rightIcon={
|
|
|
|
|
+ buttonItem.isCollabsable || buttonItem.isShowRedirectIcon ?
|
|
|
|
|
+ () => {
|
|
|
|
|
+ if(buttonItem.isCollabsable) {
|
|
|
|
|
+ if(isCollabs) {
|
|
|
|
|
+ return <ChevronDownIcon
|
|
|
|
|
+ color={isPActive ? colors.content.icon.onPrimary : colors.content.icon.low}
|
|
|
|
|
+ size={18}
|
|
|
|
|
+ />;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return <ChevronLeftIcon
|
|
|
|
|
+ color={isPActive ? colors.content.icon.onPrimary : colors.content.icon.low}
|
|
|
|
|
+ size={18}
|
|
|
|
|
+ />;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return <ChevronRightIcon
|
|
|
|
|
+ color={isPActive ? colors.content.icon.onPrimary : colors.content.icon.low}
|
|
|
|
|
+ size={18}
|
|
|
|
|
+ />;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ :
|
|
|
|
|
+ undefined
|
|
|
|
|
+ }
|
|
|
|
|
+ backgroundColor={isPActive ? "primary" : undefined}
|
|
|
|
|
+ titleColor={isPActive ? "onPrimary" : undefined}
|
|
|
|
|
+ title={buttonItem.title}
|
|
|
|
|
+ icon={buttonItem.icon}
|
|
|
|
|
+ onPress={() => {
|
|
|
|
|
+ if(buttonItem.isCollabsable) {
|
|
|
|
|
+ setIsCollabs(!isCollabs);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if(buttonItem.redirectMain || buttonItem.redirectSub) {
|
|
|
|
|
+ if(buttonItem.redirectMain && buttonItem.redirectSub) {
|
|
|
|
|
+ navigation.navigate(buttonItem.redirectMain, {
|
|
|
|
|
+ screen: buttonItem.redirectSub
|
|
|
|
|
+ });
|
|
|
|
|
+ } else if(buttonItem.redirectMain) {
|
|
|
|
|
+ navigation.navigate(buttonItem.redirectMain);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(buttonItem.props?.onPress) buttonItem.props.onPress();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ setIsPActive(isPageActive(buttonItem));
|
|
|
|
|
+
|
|
|
|
|
+ // if(closeAction && !buttonItem.isCollabsable) closeAction();
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
+ {
|
|
|
|
|
+ buttonItem.subButtons && buttonItem.subButtons.length ?
|
|
|
|
|
+ <Animated.View
|
|
|
|
|
+ onLayout={buttonItem.isCollabsable ? (event) => {
|
|
|
|
|
+ const height = event.nativeEvent.layout.height;
|
|
|
|
|
+
|
|
|
|
|
+ if(height !== 0 && measure === null) setMeasure(height);
|
|
|
|
|
+ } : undefined}
|
|
|
|
|
+ style={[
|
|
|
|
|
+ {
|
|
|
|
|
+ height: measure === null ? "auto" : animatedCollabs
|
|
|
|
|
+ }
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ {buttonItem.subButtons.map((subButtonItem, subButtonIndex) => {
|
|
|
|
|
+ return renderMenuButton(subButtonItem, subButtonIndex);
|
|
|
|
|
+ })}
|
|
|
|
|
+ </Animated.View>
|
|
|
|
|
+ :
|
|
|
|
|
+ null
|
|
|
|
|
+ }
|
|
|
|
|
+ </View>;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const renderButtons = () => {
|
|
|
|
|
+ if(!buttons || !buttons.length) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return buttons.map((buttonItem, buttonIndex) => {
|
|
|
|
|
+ return renderMenuButton(buttonItem, buttonIndex);
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const renderFooter = () => {
|
|
|
|
|
+ if(!RenderFooter) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return <RenderFooter/>;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const renderSafeAreaContext = () => {
|
|
|
|
|
+ if(!isWorkWithSafeAreaView) {
|
|
|
|
|
+ return <Fragment>
|
|
|
|
|
+ {renderHeader()}
|
|
|
|
|
+ </Fragment>;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return <SafeAreaView
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.safeAreaView
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ {renderHeader()}
|
|
|
|
|
+ <View
|
|
|
|
|
+ style={[
|
|
|
|
|
+ stylesheet.content
|
|
|
|
|
+ ]}
|
|
|
|
|
+ >
|
|
|
|
|
+ {renderButtons()}
|
|
|
|
|
+ </View>
|
|
|
|
|
+ {renderFooter()}
|
|
|
|
|
+ </SafeAreaView>;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const renderContent = () => {
|
|
const renderContent = () => {
|
|
|
return <Animated.View
|
|
return <Animated.View
|
|
|
{...props}
|
|
{...props}
|
|
@@ -218,17 +440,11 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
setMeasures(width);
|
|
setMeasures(width);
|
|
|
}}
|
|
}}
|
|
|
>
|
|
>
|
|
|
- <View
|
|
|
|
|
- style={{
|
|
|
|
|
- backgroundColor: "red",
|
|
|
|
|
- height: 300,
|
|
|
|
|
- width: 100
|
|
|
|
|
- }}
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ {renderSafeAreaContext()}
|
|
|
</Animated.View>;
|
|
</Animated.View>;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- if(isWorkWithModal) {
|
|
|
|
|
|
|
+ if(isWorkWithModal && measures !== null) {
|
|
|
return <Modal
|
|
return <Modal
|
|
|
{...modalProps}
|
|
{...modalProps}
|
|
|
isWorkWithPortal={isWorkWithPortal}
|
|
isWorkWithPortal={isWorkWithPortal}
|
|
@@ -244,7 +460,7 @@ const Menu: RefForwardingComponent<IMenuRef, IMenuProps> = ({
|
|
|
</Modal>;
|
|
</Modal>;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if(isWorkWithPortal) {
|
|
|
|
|
|
|
+ if(isWorkWithPortal && measures !== null) {
|
|
|
return <Portal
|
|
return <Portal
|
|
|
name={portalName}
|
|
name={portalName}
|
|
|
>
|
|
>
|