Skip to content

Commit

Permalink
Add SplitPage component (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshgachnang authored Apr 13, 2022
1 parent b8a004e commit c513656
Show file tree
Hide file tree
Showing 6 changed files with 323 additions and 42 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"build": "cd src && yarn build",
"dev": "cd src && yarn dev",
"local": "tsc-watch --onSuccess \"cp -a src/dist/* ../totum/node_modules/react-unifier/dist\"",
"build:web": "expo build:web",
"lint": "prettier --list-different \"src/**/*.ts\" && eslint \"src/**/*.ts*\"",
"lintfix": "eslint \"src/**/*.ts*\"",
Expand Down Expand Up @@ -283,6 +284,7 @@
"terser-webpack-plugin": "2.3.5",
"ts-loader": "^8.0.2",
"ts-pnp": "1.1.6",
"tsc-watch": "^5.0.2",
"typescript": "^3.9.7",
"url-loader": "2.3.0",
"webpack": "4.42.0",
Expand Down
5 changes: 4 additions & 1 deletion src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"main": "dist/index.js",
"scripts": {
"local": "tsc-watch --onSuccess \"cp -a dist/* ../totum/node_modules/react-unifier/dist\"",
"build": "tsc",
"dev": "tsc -w"
},
Expand Down Expand Up @@ -127,7 +128,9 @@
"resolutions": {
"update-input-width": "1.1.1"
},
"dependencies": {},
"dependencies": {
"tsc-watch": "^5.0.2"
},
"devDependencies": {},
"peerDependencies": {
"@expo/vector-icons": "^12.0.0",
Expand Down
21 changes: 19 additions & 2 deletions src/unifier/SplitPage.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,28 @@ import React from "react";
import {SplitPage} from "./SplitPage";
import {Text} from "./Text";
import {storiesOf} from "@storybook/react-native";
import {Box} from "./Box";

storiesOf("Split Page", module).add("Split", () => (
<SplitPage
navigation={{}}
renderListViewItem={(item) => <Text>name: {item.item.name}</Text>}
listViewData={[{name: "user1"}, {name: "user2"}]}
listViewWidth={250}
renderListViewItem={(item) => (
<Box color="blue" padding={2}>
<Text>name: {item.item.name}</Text>
</Box>
)}
renderListViewHeader={() => (
<Box padding={2} color="red">
<Text weight="bold">Users:</Text>
</Box>
)}
listViewData={Array.from(Array(100).keys()).map((i) => ({name: `user${i}`}))}
renderContent={(index) => (
<Box padding={2} color="lightGray">
{index === undefined && <Text weight="bold">Nothing selected</Text>}
{index !== undefined && <Text weight="bold">User {index}</Text>}
</Box>
)}
/>
));
116 changes: 79 additions & 37 deletions src/unifier/SplitPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import React from "react";
import {Box} from "./Box";
import {Color} from "./Common";
import {ErrorBoundary} from "./ErrorBoundary";
// import {KeyboardAccessoryNavigation} from "react-native-keyboard-accessory";
import {Spinner} from "./Spinner";
import {Unifier} from "./Unifier";
import {FlatList} from "./FlatList";
import {ListRenderItemInfo} from "react-native";
import {ListRenderItemInfo, View} from "react-native";
import {mediaQueryLargerThan} from "./MediaQuery";
import {Icon} from "./Icon";
import {IconButton} from "./IconButton";

interface SplitPageProps {
// TODO: figure out navigation
Expand All @@ -18,55 +20,95 @@ interface SplitPageProps {
rightButtonOnClick?: () => void;
renderListViewItem: (itemInfo: ListRenderItemInfo<any>) => React.ReactElement | null;
renderListViewHeader?: () => React.ReactElement | null;
renderContent: (index?: number) => React.ReactElement | null;
listViewData: any[];
listViewExtraData?: any;
listViewWidth?: number;
}

interface SplitPageState {}
interface SplitPageState {
selectedId?: number;
}

// A component for rendering a list on one side and a details view on the right for large screens,
// and a scrollable list where clicking an item takes you the details view.
export class SplitPage extends React.Component<SplitPageProps, SplitPageState> {
state = {selectedId: undefined};

actionSheetRef: React.RefObject<any> = React.createRef();

render() {
renderItem = (itemInfo: ListRenderItemInfo<any>) => {
return (
<ErrorBoundary>
<Box
avoidKeyboard={true}
keyboardOffset={this.props.keyboardOffset}
display="flex"
width="100%"
height="100%"
flex="grow"
direction="row"
color={this.props.color || "lightGray"}
>
{this.props.loading === true && (
<Spinner size="md" color={Unifier.theme.darkGray as any} />
)}
{/* <KeyboardAccessoryNavigation
avoidKeyboard
doneButton={true}
nextButton={true}
previousButton={true}
/> */}
<Box
onClick={() => {
this.setState({selectedId: itemInfo.index});
}}
>
{this.props.renderListViewItem(itemInfo)}
</Box>
);
};

renderList = () => {
if (!mediaQueryLargerThan("sm") && this.state.selectedId) {
return null;
}
return (
<View
style={{
width: mediaQueryLargerThan("sm") ? this.props.listViewWidth ?? 300 : "100%",
maxWidth: mediaQueryLargerThan("sm") ? this.props.listViewWidth ?? 300 : "100%",
flexGrow: 1,
flexShrink: 0,
display: "flex",
flexDirection: "column",
}}
>
{this.props.renderListViewHeader && this.props.renderListViewHeader()}
<FlatList
data={this.props.listViewData}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
extraData={this.props.listViewExtraData}
/>
</View>
);
};

{/* TODO: render this only for small sizes */}
<Box width={300} maxWidth={300} flex="shrink" direction="column" scroll={true}>
{this.props.renderListViewHeader && this.props.renderListViewHeader()}
<FlatList
data={this.props.listViewData}
renderItem={this.props.renderListViewItem}
keyExtractor={(item) => item.id}
extraData={this.props.listViewExtraData}
renderListContent = () => {
return (
<Box flex="grow" padding={2}>
{!mediaQueryLargerThan("sm") && (
<Box width="100%">
<IconButton
icon="times"
accessibilityLabel="close"
iconColor="darkGray"
onClick={() => this.setState({selectedId: undefined})}
/>
</Box>
<Box flex="grow" padding={2}>
{this.props.children}
</Box>
</Box>
</ErrorBoundary>
)}
{this.props.renderContent(this.state.selectedId)}
</Box>
);
};

render() {
return (
<Box
avoidKeyboard={true}
keyboardOffset={this.props.keyboardOffset}
display="flex"
width="100%"
height="100%"
flex="grow"
direction="row"
color={this.props.color || "lightGray"}
>
{this.props.loading === true && <Spinner size="md" color={Unifier.theme.darkGray as any} />}
{this.renderList()}
{this.renderListContent()}
</Box>
);
}
}
140 changes: 140 additions & 0 deletions src/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==

cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"

duplexer@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==

event-stream@=3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=
dependencies:
duplexer "~0.1.1"
from "~0"
map-stream "~0.1.0"
pause-stream "0.0.11"
split "0.3"
stream-combiner "~0.0.4"
through "~2.3.1"

from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=

isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=

map-stream@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=

node-cleanup@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c"
integrity sha1-esGavSl+Caf3KnFUXZUbUX5N3iw=

path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==

[email protected]:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=
dependencies:
through "~2.3"

ps-tree@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==
dependencies:
event-stream "=3.3.4"

shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
dependencies:
shebang-regex "^3.0.0"

shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==

[email protected]:
version "0.3.3"
resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=
dependencies:
through "2"

stream-combiner@~0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=
dependencies:
duplexer "~0.1.1"

string-argv@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.1.2.tgz#c5b7bc03fb2b11983ba3a72333dd0559e77e4738"
integrity sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA==

strip-ansi@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

through@2, through@~2.3, through@~2.3.1:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=

tsc-watch@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/tsc-watch/-/tsc-watch-5.0.2.tgz#4baf19af911b59e6cb1e78dcfbe8834cc2f4c238"
integrity sha512-TaOOLY2xJCorxCt6seXhNH/35p991rp2GkddSA3S8wxc6utBeVFVMFnlK8UEsf7I07So8NZ/IpDDb3nBNhN4DA==
dependencies:
cross-spawn "^7.0.3"
node-cleanup "^2.1.2"
ps-tree "^1.2.0"
string-argv "^0.1.1"
strip-ansi "^6.0.0"

[email protected]:
version "1.1.1"
resolved "https://registry.yarnpkg.com/update-input-width/-/update-input-width-1.1.1.tgz#075cad85e20f542a5eccc216937ab8d57a1ab892"
integrity sha512-khNPvsmV9CJbvOlK0Wou2FLPNcKFQepq5yKHyClxz39A3TTkCkkDOOdOs1xoMNWKTesN+qQALffoNP4P8Jydgw==

which@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
Loading

0 comments on commit c513656

Please sign in to comment.