diff --git a/package.json b/package.json index 82f8634d..6bc6dfcc 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,12 @@ "description": "ReScript bindings for react-navigation.", "version": "5.1.3", "peerDependencies": { - "@react-navigation/native": "^5.0.0", "@react-navigation/bottom-tabs": "^5.0.0", - "@react-navigation/stack": "^5.0.0", - "@react-navigation/material-top-tabs": "^5.0.0", - "@react-navigation/material-bottom-tabs": "^5.0.0", "@react-navigation/drawer": "^5.0.0", + "@react-navigation/material-bottom-tabs": "^5.0.0", + "@react-navigation/material-top-tabs": "^5.0.0", + "@react-navigation/native": "^5.0.0", + "@react-navigation/stack": "^5.0.0", "@rescript/react": "^0.10.0", "rescript-react-native": "^0.64.3" }, @@ -35,21 +35,21 @@ "format:most": "prettier --write \"**/*.{md,json,js,css}\"", "format:re": "find . -name \"*.re\" -or -name \"*.rei\" | grep -v \"node_modules\" | xargs bsrefmt --in-place", "format": "yarn format:most && yarn format:re", - "re:start": "bsb -make-world -w", - "re:build": "bsb -make-world", - "re:clean-build": "bsb -clean-world -make-world", + "re:start": "rescript -w", + "re:build": "rescript", + "re:clean-build": "rescript clean && rescript", "start": "yarn re:start", "build": "yarn re:build", "test": "yarn re:clean-build", "release": "npmpub" }, "devDependencies": { - "bs-platform": "^9.0.0", + "@rescript/react": "^0.10.0", "husky": "^4.0.0", "lint-staged": "^10.0.0", "npmpub": "^5.0.0", "prettier": "^2.0.0", - "@rescript/react": "^0.10.0", + "rescript": "^9.1.2", "rescript-react-native": "^0.64.3" }, "prettier": { diff --git a/src/BottomTabs.re b/src/BottomTabs.re deleted file mode 100644 index 46a29b1e..00000000 --- a/src/BottomTabs.re +++ /dev/null @@ -1,228 +0,0 @@ -open Core; - -type options; - -module BottomTabNavigationProp = (M: { - type params; - type options; - }) => { - include NavigationScreenProp(M); - - type t = navigation; - - [@bs.send] external jumpTo: (t, string) => unit = "jumpTo"; - [@bs.send] - external jumpToWithParams: (t, string, M.params) => unit = "jumpTo"; -}; - -module Make = (M: {type params;}) => { - type nonrec route = route(M.params); - module Navigation = - BottomTabNavigationProp({ - include M; - type nonrec options = options; - }); - - type animatedNode = ReactNative.Animated.Value.t; - - type scene = { - index: int, - focused: bool, - tintColor: string, - }; - - type labelPositionArgs = {deviceOrientation: string}; - - class type virtual baseBottomTabBarOptions = { - pub keyboardHidesTabBar: option(bool); - pub activeBackgroundColor: option(string); - pub inactiveBackgroundColor: option(string); - pub allowFontScaling: option(bool); - pub showLabel: option(bool); - pub labelStyle: option(ReactNative.Style.t); - pub tabStyle: option(ReactNative.Style.t); - pub labelPosition: option(labelPositionArgs => string); - pub adaptive: option(bool); - pub style: option(ReactNative.Style.t); - }; - - class type virtual bottomTabBarOptions = { - as 'self; - constraint 'self = #baseBottomTabBarOptions; - pub activeTintColor: option(string); - pub inactiveTintColor: option(string); - }; - - type accessibilityRole = string; - type accessibilityStates = array(string); - type routeArgs = {route}; - type renderIconArgs = { - route, - focused: bool, - tintColor: string, - horizontal: bool, - }; - class type virtual bottomTabBarProps = { - as 'self; - constraint 'self = #baseBottomTabBarOptions; - pub state: navigationState(M.params); - pub navigation: navigation; - pub onTabPress: routeArgs => unit; - pub onTabLongPress: routeArgs => unit; - pub getAccessibilityLabel: routeArgs => Js.nullable(string); - pub getAccessibilityRole: routeArgs => Js.nullable(accessibilityRole); - pub getAccessibilityStates: routeArgs => Js.nullable(accessibilityStates); - pub getButtonComponent: routeArgs => Js.nullable(React.element); - //pub getLabelText: routeArgs => ...; - pub getTestID: routeArgs => Js.nullable(string); - pub renderIcon: renderIconArgs => React.element; - pub activeTintColor: string; - pub inactiveTintColor: string; - }; - - [@bs.obj] - external bottomTabBarOptions: - ( - ~keyboardHidesTabBar: bool=?, - ~activeTintColor: string=?, - ~inactiveTintColor: string=?, - ~activeBackgroundColor: string=?, - ~inactiveBackgroundColor: string=?, - ~allowFontScaling: bool=?, - ~showLabel: bool=?, - ~showIcon: bool=?, - ~labelStyle: ReactNative.Style.t=?, - ~tabStyle: ReactNative.Style.t=?, - ~labelPosition: labelPositionArgs => string=?, - ~adaptive: bool=?, - ~style: ReactNative.Style.t=?, - unit - ) => - bottomTabBarOptions; - - type tabBarLabelArgs = { - focused: bool, - color: string, - }; - type tabBarIconArgs = { - focused: bool, - color: string, - size: float, - }; - [@bs.obj] - external options: - ( - ~title: string=?, - //TODO: dynamic, missing static option: React.ReactNode - ~tabBarLabel: tabBarLabelArgs => React.element=?, - ~tabBarIcon: tabBarIconArgs => React.element=?, - ~tabBarAccessibilityLabel: string=?, - ~tabBarTestID: string=?, - ~tabBarVisible: bool=?, - ~tabBarButton: React.element=?, - ~unmountOnBlur: bool=?, - unit - ) => - options; - - type optionsProps = { - navigation, - route, - }; - - type optionsCallback = optionsProps => options; - - type navigatorProps = { - initialRouteName: option(string), - screenOptions: option(optionsCallback), - backBehavior: option(string), - _lazy: option(bool), - tabBar: option(Js.t(bottomTabBarProps) => React.element), - tabBarOptions: option(bottomTabBarOptions), - }; - - type renderCallbackProp = { - navigation, - route, - }; - - type screenProps('params) = { - name: string, - options: option(optionsCallback), - initialParams: option('params), - component: - option( - React.component({ - . - "navigation": navigation, - "route": route, - }), - ), - children: option(renderCallbackProp => React.element), - }; - - [@bs.module "@react-navigation/bottom-tabs"] - external make: - unit => - { - . - "Navigator": navigatorProps => React.element, - "Screen": screenProps(M.params) => React.element, - } = - "createBottomTabNavigator"; - - let bottomTabs = make(); - - module Screen = { - [@bs.obj] - external makeProps: - ( - ~name: string, - ~options: optionsCallback=?, - ~initialParams: M.params=?, - ~component: React.component({ - . - "navigation": navigation, - "route": route, - }), - ~key: string=?, - unit - ) => - screenProps(M.params); - let make = bottomTabs##"Screen"; - }; - - module ScreenWithCallback = { - [@bs.obj] - external makeProps: - ( - ~name: string, - ~options: optionsCallback=?, - ~initialParams: M.params=?, - ~children: renderCallbackProp => React.element, - ~key: string=?, - unit - ) => - screenProps(M.params); - let make = bottomTabs##"Screen"; - }; - - module Navigator = { - [@bs.obj] - external makeProps: - ( - ~initialRouteName: string=?, - ~screenOptions: optionsCallback=?, - ~children: React.element, - ~backBehavior: [ | `initialRoute | `order | `history | `none]=?, - ~_lazy: bool=?, - ~tabBar: Js.t(bottomTabBarProps) => React.element=?, - ~tabBarOptions: bottomTabBarOptions=?, - ~key: string=?, - unit - ) => - navigatorProps; - - let make = bottomTabs##"Navigator"; - }; -}; diff --git a/src/BottomTabs.res b/src/BottomTabs.res new file mode 100644 index 00000000..ac9a3f2c --- /dev/null +++ b/src/BottomTabs.res @@ -0,0 +1,206 @@ +open Core + +type options + +module BottomTabNavigationProp = ( + M: { + type params + type options + }, +) => { + include NavigationScreenProp(M) + + type t = navigation + + @send external jumpTo: (t, string) => unit = "jumpTo" + @send + external jumpToWithParams: (t, string, M.params) => unit = "jumpTo" +} + +module Make = ( + M: { + type params + }, +) => { + type route = route + module Navigation = BottomTabNavigationProp({ + include M + type options = options + }) + + type animatedNode = ReactNative.Animated.Value.t + + type scene = { + index: int, + focused: bool, + tintColor: string, + } + + type labelPositionArgs = {deviceOrientation: string} + + type baseBottomTabBarOptions = { + "keyboardHidesTabBar": option, + "activeBackgroundColor": option, + "inactiveBackgroundColor": option, + "allowFontScaling": option, + "showLabel": option, + "labelStyle": option, + "tabStyle": option, + "labelPosition": option string>, + "adaptive": option, + "style": option, + } + + type bottomTabBarOptions = { + ...baseBottomTabBarOptions, + "activeTintColor": option, + "inactiveTintColor": option, + } + + @obj + external bottomTabBarOptions: ( + ~keyboardHidesTabBar: bool=?, + ~activeTintColor: string=?, + ~inactiveTintColor: string=?, + ~activeBackgroundColor: string=?, + ~inactiveBackgroundColor: string=?, + ~allowFontScaling: bool=?, + ~showLabel: bool=?, + ~labelStyle: ReactNative.Style.t=?, + ~tabStyle: ReactNative.Style.t=?, + ~labelPosition: labelPositionArgs => string=?, + ~adaptive: bool=?, + ~style: ReactNative.Style.t=?, + unit, + ) => bottomTabBarOptions = "" + + type accessibilityRole = string + type accessibilityStates = array + type routeArgs = {route: route} + type renderIconArgs = { + route: route, + focused: bool, + tintColor: string, + horizontal: bool, + } + + type bottomTabBarProps = { + ...baseBottomTabBarOptions, + "state": navigationState, + "navigation": navigation, + "onTabPress": routeArgs => unit, + "onTabLongPress": routeArgs => unit, + "getAccessibilityLabel": routeArgs => Js.nullable, + "getAccessibilityRole": routeArgs => Js.nullable, + "getAccessibilityStates": routeArgs => Js.nullable, + "getButtonComponent": routeArgs => Js.nullable, + //"getLabelText" routeArgs => ..., + "getTestID": routeArgs => Js.nullable, + "renderIcon": renderIconArgs => React.element, + "activeTintColor": string, + "inactiveTintColor": string, + } + + type tabBarLabelArgs = { + focused: bool, + color: string, + } + type tabBarIconArgs = { + focused: bool, + color: string, + size: float, + } + @obj + external options: ( + ~title: string=?, + ~tabBarLabel: //TODO: dynamic, missing static option: React.ReactNode + tabBarLabelArgs => React.element=?, + ~tabBarIcon: tabBarIconArgs => React.element=?, + ~tabBarAccessibilityLabel: string=?, + ~tabBarTestID: string=?, + ~tabBarVisible: bool=?, + ~tabBarButton: React.element=?, + ~unmountOnBlur: bool=?, + unit, + ) => options = "" + + type optionsProps = { + navigation: navigation, + route: route, + } + + type optionsCallback = optionsProps => options + + type navigatorProps = { + initialRouteName: option, + screenOptions: option, + backBehavior: option, + _lazy: option, + tabBar: option React.element>, + tabBarOptions: option, + } + + type renderCallbackProp = { + navigation: navigation, + route: route, + } + + type screenProps<'params> = { + name: string, + options: option, + initialParams: option<'params>, + component: option>, + children: option React.element>, + } + + @module("@react-navigation/bottom-tabs") + external make: unit => { + "Navigator": navigatorProps => React.element, + "Screen": screenProps => React.element, + } = "createBottomTabNavigator" + + let bottomTabs = make() + + module Screen = { + @obj + external makeProps: ( + ~name: string, + ~options: optionsCallback=?, + ~initialParams: M.params=?, + ~component: React.component<{"navigation": navigation, "route": route}>, + ~key: string=?, + unit, + ) => screenProps = "" + let make = bottomTabs["Screen"] + } + + module ScreenWithCallback = { + @obj + external makeProps: ( + ~name: string, + ~options: optionsCallback=?, + ~initialParams: M.params=?, + ~children: renderCallbackProp => React.element, + ~key: string=?, + unit, + ) => screenProps = "" + let make = bottomTabs["Screen"] + } + + module Navigator = { + @obj + external makeProps: ( + ~initialRouteName: string=?, + ~screenOptions: optionsCallback=?, + ~children: React.element, + ~backBehavior: [#initialRoute | #order | #history | #none]=?, + ~_lazy: bool=?, + ~tabBar: bottomTabBarProps => React.element=?, + ~tabBarOptions: bottomTabBarOptions=?, + ~key: string=?, + unit, + ) => navigatorProps = "" + + let make = bottomTabs["Navigator"] + } +} diff --git a/src/Core.bs.js b/src/Core.bs.js index 21c4115d..cd663764 100644 --- a/src/Core.bs.js +++ b/src/Core.bs.js @@ -1,6 +1,6 @@ 'use strict'; -var Caml_option = require("bs-platform/lib/js/caml_option.js"); +var Caml_option = require("rescript/lib/js/caml_option.js"); function NavigationHelpersCommon(M) { var navigateByKey = function (key, params, param) { @@ -18,7 +18,7 @@ function NavigationHelpersCommon(M) { name: name }; if (key !== undefined) { - tmp.key = Caml_option.valFromOption(key); + tmp.key = key; } if (params !== undefined) { tmp.params = Caml_option.valFromOption(params); @@ -52,7 +52,7 @@ function NavigationScreenProp(M) { name: name }; if (key !== undefined) { - tmp.key = Caml_option.valFromOption(key); + tmp.key = key; } if (params !== undefined) { tmp.params = Caml_option.valFromOption(params); diff --git a/src/Core.re b/src/Core.re deleted file mode 100644 index 145b7347..00000000 --- a/src/Core.re +++ /dev/null @@ -1,124 +0,0 @@ -type route('params) = { - key: string, - name: string, - params: option('params), - state: option(navigationState('params)), -} -and navigationState('params) = { - key: string, - index: int, - routeNames: array(string), - routes: array(route('params)), -}; - -type navigation; - -module NavigationHelpersCommon = (M: {type params;}) => { - type nonrec route = route(M.params); - [@bs.send] - external dispatch: (navigation, NavigationActions.action) => unit = - "dispatch"; - - [@bs.send] external navigate: (navigation, string) => unit = "navigate"; - [@bs.send] - external navigateWithParams: (navigation, string, M.params) => unit = - "navigate"; - - type navigationParams; - - [@bs.obj] - external navigateByKeyParams: - (~key: string, ~params: M.params=?, unit) => navigationParams; - - [@bs.obj] - external navigateByNameParams: - (~name: string, ~key: string=?, ~params: M.params=?, unit) => - navigationParams; - - [@bs.send] external navigateBy: navigationParams => unit = "navigate"; - - let navigateByKey = (~key: string, ~params: option(M.params)=?, _) => - navigateBy(navigateByKeyParams(~key, ~params?, ())); - - let navigateByName = - ( - ~name: string, - ~key: option(string)=?, - ~params: option(M.params)=?, - _, - ) => - navigateBy(navigateByNameParams(~name, ~key?, ~params?, ())); - - [@bs.send] external replace: (navigation, string) => unit = "replace"; - [@bs.send] - external replaceWithParams: (navigation, string, M.params) => unit = - "replace"; - - [@bs.send] - external reset: (navigation, navigationState(M.params)) => unit = "reset"; - - [@bs.send] - external resetRoot: (navigation, navigationState(M.params)) => unit = - "resetRoot"; - - [@bs.send] external goBack: (navigation, unit) => unit = "goBack"; - [@bs.send] external isFocused: (navigation, unit) => bool = "isFocused"; - [@bs.send] external canGoBack: (navigation, unit) => bool = "canGoBack"; -}; - -module EventConsumer = (M: {type params;}) => { - type eventListenerOptions('data) = { - [@bs.as "type"] - type_: string, - defaultPrevented: bool, - preventDefault: unit => unit, - data: option('data), - }; - type eventListenerCallback('data) = eventListenerOptions('data) => unit; - - type unsubscribe = unit => unit; - - [@bs.send] - external addListener: - ( - navigation, - [ | `focus | `blur | `tabPress], - eventListenerCallback('data) - ) => - unsubscribe = - "addListener"; - [@bs.send] - external removeListener: - ( - navigation, - [ | `focus | `blur | `tabPress], - eventListenerCallback('data) - ) => - unsubscribe = - "removeListener"; -}; - -module NavigationScreenProp = (M: { - type params; - type options; - }) => { - include NavigationHelpersCommon(M); - include EventConsumer(M); - - [@bs.send] external setParams: (navigation, M.params) => unit = "setParams"; - [@bs.send] - external setOptions: (navigation, M.options) => unit = "setOptions"; - - [@bs.send] - external isFirstRouteInParent: (navigation, unit) => bool = - "isFirstRouteInParent"; - - [@bs.send] - external dangerouslyGetParent: navigation => Js.nullable(navigation) = - "dangerouslyGetParent"; - - [@bs.send] - external dangerouslyGetState: - navigation => Js.nullable(navigationState('params)) = - "dangerouslyGetState"; -}; diff --git a/src/Core.res b/src/Core.res new file mode 100644 index 00000000..d3077c32 --- /dev/null +++ b/src/Core.res @@ -0,0 +1,117 @@ +type rec route<'params> = { + key: string, + name: string, + params: option<'params>, + state: option>, +} +and navigationState<'params> = { + key: string, + index: int, + routeNames: array, + routes: array>, +} + +type navigation + +module NavigationHelpersCommon = ( + M: { + type params + }, +) => { + type route = route + @send + external dispatch: (navigation, NavigationActions.action) => unit = "dispatch" + + @send external navigate: (navigation, string) => unit = "navigate" + @send + external navigateWithParams: (navigation, string, M.params) => unit = "navigate" + + type navigationParams + + @obj + external navigateByKeyParams: (~key: string, ~params: M.params=?, unit) => navigationParams = "" + + @obj + external navigateByNameParams: ( + ~name: string, + ~key: string=?, + ~params: M.params=?, + unit, + ) => navigationParams = "" + + @send external navigateBy: navigationParams => unit = "navigate" + + let navigateByKey = (~key: string, ~params: option=?, _) => + navigateBy(navigateByKeyParams(~key, ~params?, ())) + + let navigateByName = (~name: string, ~key: option=?, ~params: option=?, _) => + navigateBy(navigateByNameParams(~name, ~key?, ~params?, ())) + + @send external replace: (navigation, string) => unit = "replace" + @send + external replaceWithParams: (navigation, string, M.params) => unit = "replace" + + @send + external reset: (navigation, navigationState) => unit = "reset" + + @send + external resetRoot: (navigation, navigationState) => unit = "resetRoot" + + @send external goBack: (navigation, unit) => unit = "goBack" + @send external isFocused: (navigation, unit) => bool = "isFocused" + @send external canGoBack: (navigation, unit) => bool = "canGoBack" +} + +module EventConsumer = ( + M: { + type params + }, +) => { + type eventListenerOptions<'data> = { + @as("type") + type_: string, + defaultPrevented: bool, + preventDefault: unit => unit, + data: option<'data>, + } + type eventListenerCallback<'data> = eventListenerOptions<'data> => unit + + type unsubscribe = unit => unit + + @send + external addListener: ( + navigation, + [#focus | #blur | #tabPress], + eventListenerCallback<'data>, + ) => unsubscribe = "addListener" + @send + external removeListener: ( + navigation, + [#focus | #blur | #tabPress], + eventListenerCallback<'data>, + ) => unsubscribe = "removeListener" +} + +module NavigationScreenProp = ( + M: { + type params + type options + }, +) => { + include NavigationHelpersCommon(M) + include EventConsumer(M) + + @send external setParams: (navigation, M.params) => unit = "setParams" + @send + external setOptions: (navigation, M.options) => unit = "setOptions" + + @send + external isFirstRouteInParent: (navigation, unit) => bool = "isFirstRouteInParent" + + @send + external dangerouslyGetParent: navigation => Js.nullable = "dangerouslyGetParent" + + @send + external dangerouslyGetState: navigation => Js.nullable> = + "dangerouslyGetState" +} diff --git a/src/Drawer.re b/src/Drawer.re deleted file mode 100644 index 95b3d4af..00000000 --- a/src/Drawer.re +++ /dev/null @@ -1,167 +0,0 @@ -open Core; - -type options; - -module DrawerNavigationProp = (M: { - type params; - type options; - }) => { - include NavigationScreenProp(M); - - type t = navigation; - - [@bs.send] external openDrawer: t => unit = "openDrawer"; - [@bs.send] external closeDrawer: t => unit = "closeDrawer"; - [@bs.send] external toggleDrawer: t => unit = "toggleDrawer"; -}; - -module Make = (M: {type params;}) => { - module Navigation = - DrawerNavigationProp({ - include M; - type nonrec options = options; - }); - - type animatedNode = ReactNative.Animated.Value.t; - - type scene = { - route: route(M.params), - index: int, - focused: bool, - tintColor: option(string), - }; - - class type contentOptions = { - pub items: array(route(M.params)); - pub activeItemKey: option(Js.nullable(string)); - pub activeTintColor: option(string); - pub activeBackgroundColor: option(string); - pub inactiveTintColor: option(string); - pub inactiveBackgroundColor: option(string); - pub itemsContainerStyle: option(ReactNative.Style.t); - pub itemStyle: option(ReactNative.Style.t); - pub labelStyle: option(ReactNative.Style.t); - pub activeLabelStyle: option(ReactNative.Style.t); - pub inactiveLabelStyle: option(ReactNative.Style.t); - pub iconContainerStyle: option(ReactNative.Style.t); - }; - - class type virtual drawerNavigationItemsProps = { - as 'self; - constraint 'self = #contentOptions; - pub drawerPosition: string; - pub getLabel: scene => React.element; - pub renderIcon: scene => React.element; - pub onItemPress: scene => unit; - }; - - class type virtual contentComponentProps = { - as 'self; - constraint 'self = #drawerNavigationItemsProps; - pub navigation: navigation; - pub drawerOpenProgress: animatedNode; - }; - - [@bs.obj] - external options: - ( - ~title: string=?, - ~drawerLabel: scene => React.element=?, - ~drawerIcon: scene => React.element=?, - ~drawerLockMode: [@bs.string] [ - | `unlocked - | [@bs.as "locked-closed"] `lockedClosed - | [@bs.as "locked-open"] `lockedOpen - ] - =?, - unit - ) => - options; - - type optionsProps = { - navigation, - route: route(M.params), - }; - - type optionsCallback = optionsProps => options; - - type navigatorProps; - - type screenProps; - - [@bs.module "@react-navigation/drawer"] - external make: - unit => - { - . - "Navigator": navigatorProps => React.element, - "Screen": screenProps => React.element, - } = - "createDrawerNavigator"; - - let stack = make(); - - module Screen = { - [@bs.obj] - external makeProps: - ( - ~name: string, - ~options: optionsCallback=?, - ~initialParams: M.params=?, - ~component: React.component({ - . - "navigation": navigation, - "route": route(M.params), - }), - ~key: string=?, - unit - ) => - screenProps; - let make = stack##"Screen"; - }; - - module Navigator = { - [@bs.obj] - external makeProps: - ( - ~initialRouteName: string=?, - ~screenOptions: optionsCallback=?, - ~children: React.element, - ~backBehavior: [ | `initialRoute | `order | `history | `none]=?, - //DrawerNavigationConfig - ~drawerBackgroundColor: string=?, - ~drawerPosition: [ | `left | `right]=?, - ~drawerType: [ | `front | `back | `slide | `permanent]=?, - /* - ~drawerWidth: [@bs.unwrap] [ - | `Static(float) - | `Dynamic(unit => float) - ] - - */ - ~drawerWidth: unit => float, - ~edgeWidth: float=?, - ~hideStatusBar: bool=?, - ~keyboardDismissMode: [@bs.string] [ - | [@bs.as "on-drag"] `onDrag - | `none - ] - =?, - ~minSwipeDistance: float=?, - ~overlayColor: string=?, - ~statusBarAnimation: [ | `slide | `none | `fade]=?, - //TODO: ~gestureHandlerProps: React.ComponentProps; - ~_lazy: bool=?, - ~unmountInactiveRoutes: bool=?, - ~drawerContent: React.component(Js.t(contentComponentProps))=?, - ~drawerContentOptions: Js.t(contentOptions)=?, - ~sceneContainerStyle: ReactNative.Style.t=?, - ~style: ReactNative.Style.t=?, - ~key: string=?, - unit - ) => - navigatorProps; - - let make = stack##"Navigator"; - }; -}; diff --git a/src/Drawer.res b/src/Drawer.res new file mode 100644 index 00000000..f2463933 --- /dev/null +++ b/src/Drawer.res @@ -0,0 +1,156 @@ +open Core + +type options + +module DrawerNavigationProp = ( + M: { + type params + type options + }, +) => { + include NavigationScreenProp(M) + + type t = navigation + + @send external openDrawer: t => unit = "openDrawer" + @send external closeDrawer: t => unit = "closeDrawer" + @send external toggleDrawer: t => unit = "toggleDrawer" +} + +module Make = ( + M: { + type params + }, +) => { + module Navigation = DrawerNavigationProp({ + include M + type options = options + }) + + type animatedNode = ReactNative.Animated.Value.t + + type scene = { + route: route, + index: int, + focused: bool, + tintColor: option, + } + + type contentOptions = { + "items": array>, + "activeItemKey": option>, + "activeTintColor": option, + "activeBackgroundColor": option, + "inactiveTintColor": option, + "inactiveBackgroundColor": option, + "itemsContainerStyle": option, + "itemStyle": option, + "labelStyle": option, + "activeLabelStyle": option, + "inactiveLabelStyle": option, + "iconContainerStyle": option, + } + + type drawerNavigationItemsProps = { + ...contentOptions, + "drawerPosition": string, + "getLabel": scene => React.element, + "renderIcon": scene => React.element, + "onItemPress": scene => unit, + } + + type contentComponentProps = { + ...drawerNavigationItemsProps, + "navigation": navigation, + "drawerOpenProgress": animatedNode, + } + + @obj + external options: ( + ~title: string=?, + ~drawerLabel: scene => React.element=?, + ~drawerIcon: scene => React.element=?, + ~drawerLockMode: @string + [ + | #unlocked + | @as("locked-closed") #lockedClosed + | @as("locked-open") #lockedOpen + ]=?, + unit, + ) => options = "" + + type optionsProps = { + navigation: navigation, + route: route, + } + + type optionsCallback = optionsProps => options + + type navigatorProps + + type screenProps + + @module("@react-navigation/drawer") + external make: unit => { + "Navigator": navigatorProps => React.element, + "Screen": screenProps => React.element, + } = "createDrawerNavigator" + + let stack = make() + + module Screen = { + @obj + external makeProps: ( + ~name: string, + ~options: optionsCallback=?, + ~initialParams: M.params=?, + ~component: React.component<{"navigation": navigation, "route": route}>, + ~key: string=?, + unit, + ) => screenProps = "" + let make = stack["Screen"] + } + + module Navigator = { + @obj + external makeProps: ( + ~initialRouteName: string=?, + ~screenOptions: optionsCallback=?, + ~children: React.element, + ~backBehavior: [#initialRoute | #order | #history | #none]=?, + ~drawerBackgroundColor: //DrawerNavigationConfig + string=?, + ~drawerPosition: [#left | #right]=?, + ~drawerType: [#front | #back | #slide | #permanent]=?, + ~drawerWidth: /* + ~drawerWidth: [@bs.unwrap] [ + | `Static(float) + | `Dynamic(unit => float) + ] + + */ + unit => float, + ~edgeWidth: float=?, + ~hideStatusBar: bool=?, + ~keyboardDismissMode: @string + [ + | @as("on-drag") #onDrag + | #none + ]=?, + ~minSwipeDistance: float=?, + ~overlayColor: string=?, + ~statusBarAnimation: [#slide | #none | #fade]=?, + ~_lazy: //TODO: ~gestureHandlerProps: React.ComponentProps; + bool=?, + ~unmountInactiveRoutes: bool=?, + ~drawerContent: React.component=?, + ~drawerContentOptions: contentOptions=?, + ~sceneContainerStyle: ReactNative.Style.t=?, + ~style: ReactNative.Style.t=?, + ~key: string=?, + unit, + ) => navigatorProps = "" + + let make = stack["Navigator"] + } +} diff --git a/src/Example.re b/src/Example.re deleted file mode 100644 index 0d8a100a..00000000 --- a/src/Example.re +++ /dev/null @@ -1,67 +0,0 @@ -// Uncomment this to compile this example outside of this repo -// in this example it's not necessary (since we are running it in the module repo itself) -// open ReactNavigation; -module HomeScreen = { - open ReactNative; - [@react.component] - let make = (~navigation as _, ~route as _) => - {j|Hello Reasonable Person!|j}->React.string ; -}; - -module ModalScreen = { - open ReactNative; - [@react.component] - let make = (~navigation as _, ~route as _) => - {j|Hello From Modal|j}->React.string ; -}; - -module MainStackScreen = { - open ReactNative; - module StakeParams = { - type params = {name: string}; - }; - include Stack.Make(StakeParams); - [@react.component] - let make = (~navigation as _, ~route as _) => - - - options( - ~headerRight= - _ => -