-
-
Save Aryk/132a746976d48c9959a9eef605217361 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {MutableRefObject, useContext, useLayoutEffect, useRef} from "react"; | |
import {cast, types} from "mobx-state-tree"; | |
import Animated from "react-native-reanimated"; | |
import {observer} from "mobx-react"; | |
import BottomSheet from "reanimated-bottom-sheet"; | |
import {View, Icon} from "native-base"; | |
import {includes} from "lodash"; | |
import {TouchableWithoutFeedback} from "react-native"; | |
type BottomSheetModalNameType = "networkSortOptions"; | |
const bottomSheetModalNames: BottomSheetModalNameType[] = ["networkSortOptions"]; | |
const ButtonSheetModalsStore = types. | |
model("ButtonSheetModalsStore", { | |
modalsRendered: types.array(types.enumeration<BottomSheetModalNameType>("modalsRendered", bottomSheetModalNames)), | |
}).actions(self => ({ | |
addRenderBottomSheetModals: (bottomSheetModal: BottomSheetModalNameType) => { | |
if (!includes(self.modalsRendered, bottomSheetModal)) | |
self.modalsRendered = cast(self.modalsRendered.concat(bottomSheetModal as BottomSheetModalNameType)); | |
}, | |
removeRenderBottomSheetModals: (bottomSheetModal: BottomSheetModalNameType) => { | |
if (includes(self.modalsRendered, bottomSheetModal)) | |
self.modalsRendered = cast(self.modalsRendered.filter(r => r !== "networkSortOptions")); | |
}, | |
})); | |
const bottomSheetModalsStore = ButtonSheetModalsStore.create({ | |
modalsRendered: [] | |
}); | |
const useBottomSheetModal = (modalName: BottomSheetModalNameType) => { | |
const context = useContext(BottomSheetModalContext); | |
useLayoutEffect(() => { | |
bottomSheetModalsStore.addRenderBottomSheetModals(modalName); | |
return () => bottomSheetModalsStore.removeRenderBottomSheetModals(modalName); | |
}, []); | |
return context[modalName]; | |
}; | |
interface ICreateBottomSheetModal<K> { | |
height: number; | |
renderContent: (props: {bottomSheetModalToggler: IBottomSheetModalToggler} & K) => React.ReactNode; | |
} | |
const bottomSheetModalsComponents = {}; | |
function createBottomSheetModal<K>(name: BottomSheetModalNameType, {height, renderContent}: ICreateBottomSheetModal<K>) { | |
const RenderContent = renderContent as any; | |
bottomSheetModalsComponents[name] = ({callbackNode, bottomSheetModalToggler}) => <BottomSheet | |
ref={bottomSheetModalToggler.ref} | |
snapPoints={[height, 0]} | |
initialSnap={1} | |
renderContent={() => <View style={{backgroundColor: "#FFF", width: "100%", height: "100%", flexDirection: "column"}}> | |
<Icon | |
name="drag-handle" | |
type="MaterialIcons" | |
style={{alignSelf: "center", color: "#CCC", fontSize: 50, height: 23, marginTop: -10}} | |
/> | |
<RenderContent bottomSheetModalToggler={bottomSheetModalToggler} /> | |
</View> | |
} | |
borderRadius={10} | |
callbackNode={callbackNode} | |
/>; | |
} | |
interface IBottomSheetModalToggler { | |
ref: MutableRefObject<null>; | |
show: () => any; | |
hide: () => any; | |
} | |
type IBottomSheetModalTogglers = { | |
[name in BottomSheetModalNameType]: IBottomSheetModalToggler; | |
}; | |
const BottomSheetModalContext = React.createContext(null); | |
const BottomSheetModalCollection = observer(({children, callbackNode, bottomSheetModalTogglers}) => <> | |
{bottomSheetModalsStore.modalsRendered.map(name => { | |
const Component = bottomSheetModalsComponents[name]; | |
return <Component | |
bottomSheetModalToggler={bottomSheetModalTogglers[name]} | |
callbackNode={callbackNode} | |
key={name} | |
/>; | |
})} | |
<BottomSheetModalContext.Provider value={bottomSheetModalTogglers}> | |
{children} | |
</BottomSheetModalContext.Provider> | |
</>); | |
const BottomSheetModals = ({children}) => { | |
const animatedValue = new Animated.Value(1); | |
const bottomSheetModalTogglers = {} as IBottomSheetModalTogglers; | |
bottomSheetModalNames.forEach(name => { | |
const ref = useRef(null); | |
const show = () => ref.current?.snapTo(0); | |
const hide = () => ref.current?.snapTo(1); | |
bottomSheetModalTogglers[name] = {ref, show, hide}; | |
}); | |
const hideAllModals = () => | |
bottomSheetModalsStore.modalsRendered.forEach(name => bottomSheetModalTogglers[name].hide()); | |
return <> | |
<Animated.View | |
style={{ | |
opacity: Animated.multiply(Animated.sub(1, animatedValue), 0.7), | |
backgroundColor: "black", | |
left: 0, | |
top: 0, | |
// Make sure dark screen goes under everything when not active. | |
zIndex: Animated.cond(Animated.lessThan(animatedValue, 1), 1, 0), | |
width: "100%", | |
height: "100%", | |
position: "absolute" | |
}} | |
> | |
<TouchableWithoutFeedback onPress={hideAllModals} > | |
<View style={{width: "100%", height: "100%"}} /> | |
</TouchableWithoutFeedback> | |
</Animated.View> | |
<BottomSheetModalCollection callbackNode={animatedValue} {...{bottomSheetModalTogglers}}> | |
{children} | |
</BottomSheetModalCollection> | |
</>; | |
}; | |
export { BottomSheetModals, createBottomSheetModal, useBottomSheetModal, bottomSheetModalsStore, | |
bottomSheetModalNames, BottomSheetModalNameType, BottomSheetModalContext }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment