diff --git a/react-native/components/createStackRoutingComponent/index.tsx b/react-native/components/createStackRoutingComponent/index.tsx index 6f72028d..7321601e 100644 --- a/react-native/components/createStackRoutingComponent/index.tsx +++ b/react-native/components/createStackRoutingComponent/index.tsx @@ -98,10 +98,12 @@ export const createStackRoutingComponent = < }} onBack={props.onBack} allowsSwiping={ - index > 0 && index === props.routeState.length - 1 + index > 0 && + index === props.routeState.length - 1 && + routeTable[item.key].allowsSwiping } > - {React.createElement(routeTable[item.key], { + {React.createElement(routeTable[item.key].component, { parameters: item.parameters, push: (...itemsToAdd) => { props.setRouteState([...props.routeState, ...itemsToAdd]); diff --git a/react-native/components/createStackRoutingComponent/unit.tsx b/react-native/components/createStackRoutingComponent/unit.tsx index 893ac83b..dc292493 100644 --- a/react-native/components/createStackRoutingComponent/unit.tsx +++ b/react-native/components/createStackRoutingComponent/unit.tsx @@ -34,35 +34,44 @@ test(`can render one item`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -114,7 +123,7 @@ test(`can render one item`, async () => { onBack, allowsSwiping: false, children: expect.objectContaining({ - type: RouteB, + type: RouteB.component, props: { push: expect.any(Function), pop: expect.any(Function), @@ -168,35 +177,44 @@ test(`does not hook the back button for a single item`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -274,35 +292,44 @@ test(`can render two items`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -362,7 +389,7 @@ test(`can render two items`, async () => { onBack, allowsSwiping: false, children: expect.objectContaining({ - type: RouteB, + type: RouteB.component, props: { push: expect.any(Function), pop: expect.any(Function), @@ -400,7 +427,7 @@ test(`can render two items`, async () => { onBack, allowsSwiping: true, children: expect.objectContaining({ - type: RouteA, + type: RouteA.component, props: { push: expect.any(Function), pop: expect.any(Function), @@ -455,35 +482,44 @@ test(`hooks the back button for two items`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -569,35 +605,44 @@ test(`can render three items`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -665,7 +710,7 @@ test(`can render three items`, async () => { onBack, allowsSwiping: false, children: expect.objectContaining({ - type: RouteB, + type: RouteB.component, props: { push: expect.any(Function), pop: expect.any(Function), @@ -703,7 +748,7 @@ test(`can render three items`, async () => { onBack, allowsSwiping: false, children: expect.objectContaining({ - type: RouteA, + type: RouteA.component, props: { push: expect.any(Function), pop: expect.any(Function), @@ -741,7 +786,7 @@ test(`can render three items`, async () => { onBack, allowsSwiping: true, children: expect.objectContaining({ - type: RouteA, + type: RouteA.component, props: { push: expect.any(Function), pop: expect.any(Function), @@ -796,35 +841,44 @@ test(`hooks the back button for three items`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -892,7 +946,7 @@ test(`hooks the back button for three items`, async () => { renderer.unmount(); }); -test(`pops one card on confirming after pressing the back button`, async () => { +test(`can disable swiping to go back`, async () => { type ParametersA = { readonly testRouteAParameterKey: | `Test Route A Parameter Value A` @@ -917,36 +971,281 @@ test(`pops one card on confirming after pressing the back button`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: false, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); + const routeTable: StackRouteTable = { + testRouteAKey: RouteA, + testRouteBKey: RouteB, + testRouteCKey: RouteC, + }; - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - + const routeState: StackRouterState = [ + { + uuid: `ec055b0f-0659-4e9a-a889-06a7586bb61a`, + key: `testRouteBKey`, + parameters: { + testRouteBParameterKey: `Test Route B Parameter Value`, + }, + }, + { + uuid: `f36ce5e7-d37e-443a-8635-718118c27128`, + key: `testRouteAKey`, + parameters: { + testRouteAParameterKey: `Test Route A Parameter Value A`, + }, + }, + { + uuid: `345d1eff-3d1d-4d93-8136-e0c3ff0f7f7c`, + key: `testRouteAKey`, + parameters: { + testRouteAParameterKey: `Test Route A Parameter Value B`, + }, + }, + ]; + + const setRouteState = jest.fn(); + const onBack = jest.fn(); + + const Component = createStackRoutingComponent(routeTable); + + await new Promise((resolve) => { + setTimeout(resolve, 100); + }); + + const renderer = TestRenderer.create( + ); + expect(renderer.toTree()?.rendered).toEqual([ + expect.objectContaining({ + type: View, + props: expect.objectContaining({ + style: { + position: `absolute`, + width: `100%`, + height: `100%`, + display: `none`, + }, + pointerEvents: `none`, + children: expect.objectContaining({ + type: Card, + props: { + pop: expect.any(Function), + onBack, + allowsSwiping: false, + children: expect.objectContaining({ + type: RouteB.component, + props: { + push: expect.any(Function), + pop: expect.any(Function), + replace: expect.any(Function), + reset: expect.any(Function), + setParameters: expect.any(Function), + bottom: true, + top: false, + parameters: { + testRouteBParameterKey: `Test Route B Parameter Value`, + }, + routeState: routeState, + setRouteState: setRouteState, + exampleOtherPropKey: `Example Other Prop Value`, + onBack, + }, + }), + }, + }), + }), + }), + expect.objectContaining({ + type: View, + props: { + style: { + position: `absolute`, + width: `100%`, + height: `100%`, + }, + pointerEvents: `none`, + children: expect.objectContaining({ + type: Card, + props: { + pop: expect.any(Function), + onBack, + allowsSwiping: false, + children: expect.objectContaining({ + type: RouteA.component, + props: { + push: expect.any(Function), + pop: expect.any(Function), + replace: expect.any(Function), + reset: expect.any(Function), + setParameters: expect.any(Function), + bottom: false, + top: false, + parameters: { + testRouteAParameterKey: `Test Route A Parameter Value A`, + }, + routeState: routeState, + setRouteState: setRouteState, + exampleOtherPropKey: `Example Other Prop Value`, + onBack, + }, + }), + }, + }), + }, + }), + expect.objectContaining({ + type: View, + props: { + style: { + position: `absolute`, + width: `100%`, + height: `100%`, + }, + pointerEvents: `auto`, + children: expect.objectContaining({ + type: Card, + props: { + pop: expect.any(Function), + onBack, + allowsSwiping: false, + children: expect.objectContaining({ + type: RouteA.component, + props: { + push: expect.any(Function), + pop: expect.any(Function), + replace: expect.any(Function), + reset: expect.any(Function), + setParameters: expect.any(Function), + bottom: false, + top: true, + parameters: { + testRouteAParameterKey: `Test Route A Parameter Value B`, + }, + routeState: routeState, + setRouteState: setRouteState, + exampleOtherPropKey: `Example Other Prop Value`, + onBack, + }, + }), + }, + }), + }, + }), + ]); + + expect(setRouteState).not.toHaveBeenCalled(); + expect(onBack).not.toHaveBeenCalled(); + + renderer.unmount(); +}); + +test(`pops one card on confirming after pressing the back button`, async () => { + type ParametersA = { + readonly testRouteAParameterKey: + | `Test Route A Parameter Value A` + | `Test Route A Parameter Value B`; + }; + + type ParametersB = { + readonly testRouteBParameterKey: `Test Route B Parameter Value`; + }; + + type ParametersC = { + readonly testRouteCParameterKey: `Test Route C Parameter Value`; + }; + + type Parameters = { + testRouteAKey: ParametersA; + testRouteBKey: ParametersB; + testRouteCKey: ParametersC; + }; + + type OtherProps = { + exampleOtherPropKey: `Example Other Prop Value`; + }; + + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + const routeTable: StackRouteTable = { testRouteAKey: RouteA, testRouteBKey: RouteB, @@ -1056,35 +1355,44 @@ test(`does nothing on cancelling after pressing the back button`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -1183,35 +1491,44 @@ test(`push`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -1354,35 +1671,44 @@ test(`pop`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -1482,35 +1808,44 @@ test(`pop default`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -1617,35 +1952,44 @@ test(`card pop`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -1752,35 +2096,44 @@ test(`replace`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -1924,35 +2277,44 @@ test(`reset`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, @@ -2075,35 +2437,44 @@ test(`setParameters`, async () => { exampleOtherPropKey: `Example Other Prop Value`; }; - const RouteA: StackRoute = ({ - parameters: { testRouteAParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route A with parameter {testRouteAParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteB: StackRoute = ({ - parameters: { testRouteBParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route B with parameter {testRouteBParameterKey}{" "} - {exampleOtherPropKey} - - ); - - const RouteC: StackRoute = ({ - parameters: { testRouteCParameterKey }, - exampleOtherPropKey, - }) => ( - - Example Route C with parameter {testRouteCParameterKey}{" "} - {exampleOtherPropKey} - - ); + const RouteA: StackRoute = { + component: ({ + parameters: { testRouteAParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route A with parameter {testRouteAParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteB: StackRoute = { + component: ({ + parameters: { testRouteBParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route B with parameter {testRouteBParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; + + const RouteC: StackRoute = { + component: ({ + parameters: { testRouteCParameterKey }, + exampleOtherPropKey, + }) => ( + + Example Route C with parameter {testRouteCParameterKey}{" "} + {exampleOtherPropKey} + + ), + allowsSwiping: true, + }; const routeTable: StackRouteTable = { testRouteAKey: RouteA, diff --git a/react-native/types/StackRoute/index.tsx b/react-native/types/StackRoute/index.tsx index 449fe9b3..d525339b 100644 --- a/react-native/types/StackRoute/index.tsx +++ b/react-native/types/StackRoute/index.tsx @@ -34,84 +34,93 @@ export type StackRoute< TRouteParameters extends RouteParameters, TRouteKey extends keyof TRouteParameters, TOtherProps extends { readonly [key: string]: unknown } -> = React.FunctionComponent< - { - /** - * Call to add one or more card(s) to the top of the stack. - * @param itemsToAdd The card(s) to add. - */ - push(...itemsToAdd: ReadonlyArray>): void; +> = { + readonly component: React.FunctionComponent< + { + /** + * Call to add one or more card(s) to the top of the stack. + * @param itemsToAdd The card(s) to add. + */ + push(...itemsToAdd: ReadonlyArray>): void; - /** - * Pops one or more card(s) from the top of the stack. - * @param numberOfItemsToRemove The number of card(s) to remove. Defaults - * to 1 when not given. - */ - pop(numberOfItemsToRemove?: number): void; + /** + * Pops one or more card(s) from the top of the stack. + * @param numberOfItemsToRemove The number of card(s) to remove. Defaults + * to 1 when not given. + */ + pop(numberOfItemsToRemove?: number): void; - /** - * Pops one or more card(s) from the top of stack, then adds one or more - * card(s) to the top of the stack in their place. - * @param numberOfItemsToRemove The number of card(s) to remove. - * @param itemsToAdd The card(s) to add in their place. - */ - replace( - numberOfItemsToRemove: number, - ...itemsToAdd: ReadonlyArray> - ): void; + /** + * Pops one or more card(s) from the top of stack, then adds one or more + * card(s) to the top of the stack in their place. + * @param numberOfItemsToRemove The number of card(s) to remove. + * @param itemsToAdd The card(s) to add in their place. + */ + replace( + numberOfItemsToRemove: number, + ...itemsToAdd: ReadonlyArray> + ): void; - /** - * Resets the entire card stack to a new stack. - * @param replacementItems The replacement stack. - */ - reset(...replacementItems: ReadonlyArray>): void; + /** + * Resets the entire card stack to a new stack. + * @param replacementItems The replacement stack. + */ + reset(...replacementItems: ReadonlyArray>): void; - /** - * Changes the parameters of this card. - * @param parameters The replacement parameters. - */ - setParameters(parameters: TRouteParameters[TRouteKey]): void; + /** + * Changes the parameters of this card. + * @param parameters The replacement parameters. + */ + setParameters(parameters: TRouteParameters[TRouteKey]): void; - /** - * The route parameters for this card. - */ - readonly parameters: TRouteParameters[TRouteKey]; + /** + * The route parameters for this card. + */ + readonly parameters: TRouteParameters[TRouteKey]; - /** - * The state of the stack router. - */ - readonly routeState: StackRouterState; + /** + * The state of the stack router. + */ + readonly routeState: StackRouterState; - /** - * Sets a new state within the stack router. - * @param to The new state to set. - */ - setRouteState(to: StackRouterState): void; + /** + * Sets a new state within the stack router. + * @param to The new state to set. + */ + setRouteState(to: StackRouterState): void; - /** - * This function should not be used by your routes and is included here as - * an implementation oversight. Called when the user makes a gesture to go - * back, e.g. swiping from the left or pressing the hardware "back" button. - * @param pop Call to proceed, popping the current card from the top of - * the stack. - * @param cancel Call to cancel; for a swipe gesture, this will unswipe the - * top card. - */ - onBack(pop: () => void, cancel: () => void): void; + /** + * This function should not be used by your routes and is included here as + * an implementation oversight. Called when the user makes a gesture to go + * back, e.g. swiping from the left or pressing the hardware "back" button. + * @param pop Call to proceed, popping the current card from the top of + * the stack. + * @param cancel Call to cancel; for a swipe gesture, this will unswipe the + * top card. + */ + onBack(pop: () => void, cancel: () => void): void; - /** - * When true, the card is at the top of the stack and is visible (unless - * something else like a parent tab router is hiding the stack itself). It - * is otherwise underneath another card. Note that swiping to go back may - * reveal a card which is not top! - */ - readonly top: boolean; + /** + * When true, the card is at the top of the stack and is visible (unless + * something else like a parent tab router is hiding the stack itself). It + * is otherwise underneath another card. Note that swiping to go back may + * reveal a card which is not top! + */ + readonly top: boolean; - /** - * When true, the card is at the bottom of the stack and it is not possible - * to pop it (as there would be no card underneath to reveal). When false, - * at least one card is beneath this one to which it is possible to pop. - */ - readonly bottom: boolean; - } & TOtherProps ->; + /** + * When true, the card is at the bottom of the stack and it is not possible + * to pop it (as there would be no card underneath to reveal). When false, + * at least one card is beneath this one to which it is possible to pop. + */ + readonly bottom: boolean; + } & TOtherProps + >; + + /** + * When true, the card can be swiped away to dismiss it (e.g. the left edge page-turning gesture on iOS/Android). + * It may be necessary to set this to false when cards include draggable elements, as the touch handler on the card can interfere with those of its contents. + * This does NOT affect hardware back buttons. + */ + readonly allowsSwiping: boolean; +}; diff --git a/react-native/types/StackRoute/readme.md b/react-native/types/StackRoute/readme.md index aa1b7f2d..66c9a01b 100644 --- a/react-native/types/StackRoute/readme.md +++ b/react-native/types/StackRoute/readme.md @@ -1,6 +1,7 @@ # `react-native-app-helpers/StackRoute` -A React component which can be used to render a route within a stack router. +A React component which can be used to render a route within a stack router, +and some metadata for doing so. ## Usage @@ -23,11 +24,14 @@ type OtherProps = { otherPropKey: `Other Prop Value`, }; -const route: StackRoute = ({ - reset, push, pop, replace, bottom, top, - parameters, - otherPropKey, -}) => - {/* Your view goes here. */} -; +const route: StackRoute = { + component: ({ + reset, push, pop, replace, bottom, top, + parameters, + otherPropKey, + }) => + {/* Your view goes here. */} + , + allowsSwiping: true, +}; ``` diff --git a/react-native/types/StackRouteTable/readme.md b/react-native/types/StackRouteTable/readme.md index cfef05a9..d5d14f03 100644 --- a/react-native/types/StackRouteTable/readme.md +++ b/react-native/types/StackRouteTable/readme.md @@ -24,28 +24,37 @@ type OtherProps = { }; const route: StackRouteTable = { - routeAKey: ({ - reset, push, pop, replace, - parameters: { routeAParameterKey }, - otherPropKey, - }) => - {/* Your view goes here. */} - , - - routeBKey: ({ - reset, push, pop, replace, - parameters: { routeBParameterKey }, - otherPropKey, - }) => - {/* Your view goes here. */} - , - - routeCKey: ({ - reset, push, pop, replace, - parameters: { routeCParameterKey }, - otherPropKey, - }) => - {/* Your view goes here. */} - , + routeAKey: { + component: ({ + reset, push, pop, replace, + parameters: { routeAParameterKey }, + otherPropKey, + }) => + {/* Your view goes here. */} + , + allowsSwiping: true, + }, + + routeBKey: { + component: ({ + reset, push, pop, replace, + parameters: { routeBParameterKey }, + otherPropKey, + }) => + {/* Your view goes here. */} + , + allowsSwiping: false, + }, + + routeCKey: { + component: ({ + reset, push, pop, replace, + parameters: { routeCParameterKey }, + otherPropKey, + }) => + {/* Your view goes here. */} + , + allowsSwiping: true, + }, }; ```