ferns-ui 0.36.4 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Banner.d.ts +6 -16
- package/dist/Banner.js +52 -43
- package/dist/Banner.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/useStoredState.d.ts +1 -0
- package/dist/useStoredState.js +33 -0
- package/dist/useStoredState.js.map +1 -0
- package/package.json +55 -56
- package/src/ActionSheet.tsx +1231 -0
- package/src/Avatar.tsx +317 -0
- package/src/Badge.tsx +65 -0
- package/src/Banner.tsx +149 -0
- package/src/BlurBox.native.tsx +40 -0
- package/src/BlurBox.tsx +31 -0
- package/src/Body.tsx +32 -0
- package/src/Box.tsx +308 -0
- package/src/Button.tsx +219 -0
- package/src/Card.tsx +23 -0
- package/src/CheckBox.tsx +118 -0
- package/src/Common.ts +2743 -0
- package/src/Constants.ts +53 -0
- package/src/CustomSelect.tsx +85 -0
- package/src/DateTimeActionSheet.tsx +409 -0
- package/src/DateTimeField.android.tsx +101 -0
- package/src/DateTimeField.ios.tsx +83 -0
- package/src/DateTimeField.tsx +69 -0
- package/src/DecimalRangeActionSheet.tsx +113 -0
- package/src/ErrorBoundary.tsx +37 -0
- package/src/ErrorPage.tsx +44 -0
- package/src/FernsProvider.tsx +21 -0
- package/src/Field.tsx +299 -0
- package/src/FieldWithLabels.tsx +36 -0
- package/src/FlatList.tsx +2 -0
- package/src/Form.tsx +182 -0
- package/src/HeaderButtons.tsx +107 -0
- package/src/Heading.tsx +53 -0
- package/src/HeightActionSheet.tsx +104 -0
- package/src/Hyperlink.tsx +181 -0
- package/src/Icon.tsx +24 -0
- package/src/IconButton.tsx +165 -0
- package/src/Image.tsx +50 -0
- package/src/ImageBackground.tsx +14 -0
- package/src/InfoTooltipButton.tsx +23 -0
- package/src/Layer.tsx +17 -0
- package/src/Link.tsx +17 -0
- package/src/Mask.tsx +21 -0
- package/src/MediaQuery.ts +46 -0
- package/src/Meta.tsx +9 -0
- package/src/Modal.tsx +248 -0
- package/src/ModalSheet.tsx +58 -0
- package/src/NumberPickerActionSheet.tsx +66 -0
- package/src/Page.tsx +133 -0
- package/src/Permissions.ts +44 -0
- package/src/PickerSelect.tsx +553 -0
- package/src/Pill.tsx +24 -0
- package/src/Pog.tsx +87 -0
- package/src/ProgressBar.tsx +55 -0
- package/src/ScrollView.tsx +2 -0
- package/src/SegmentedControl.tsx +102 -0
- package/src/SelectList.tsx +89 -0
- package/src/SideDrawer.tsx +62 -0
- package/src/Spinner.tsx +20 -0
- package/src/SplitPage.native.tsx +160 -0
- package/src/SplitPage.tsx +302 -0
- package/src/Switch.tsx +19 -0
- package/src/Table.tsx +87 -0
- package/src/TableHeader.tsx +36 -0
- package/src/TableHeaderCell.tsx +76 -0
- package/src/TableRow.tsx +87 -0
- package/src/TapToEdit.tsx +221 -0
- package/src/Text.tsx +131 -0
- package/src/TextArea.tsx +16 -0
- package/src/TextField.tsx +401 -0
- package/src/TextFieldNumberActionSheet.tsx +61 -0
- package/src/Toast.tsx +106 -0
- package/src/Tooltip.tsx +269 -0
- package/src/UnifiedScreens.ts +24 -0
- package/src/Unifier.ts +371 -0
- package/src/Utilities.tsx +159 -0
- package/src/WithLabel.tsx +57 -0
- package/src/dayjsExtended.ts +10 -0
- package/src/index.tsx +1347 -0
- package/src/polyfill.d.ts +11 -0
- package/src/tableContext.tsx +80 -0
- package/src/useStoredState.ts +39 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import {Box} from "./Box";
|
|
4
|
+
import {SegmentedControlProps} from "./Common";
|
|
5
|
+
import {Text} from "./Text";
|
|
6
|
+
|
|
7
|
+
export const SegmentedControl = ({
|
|
8
|
+
items,
|
|
9
|
+
onChange = () => {},
|
|
10
|
+
selectedItemIndexes = undefined,
|
|
11
|
+
selectedItemIndex = undefined,
|
|
12
|
+
multiselect = false,
|
|
13
|
+
selectLimit = 1,
|
|
14
|
+
}: SegmentedControlProps) => {
|
|
15
|
+
const renderItem = (item: string | React.ReactNode) => {
|
|
16
|
+
return (
|
|
17
|
+
<Text align="center" weight="bold">
|
|
18
|
+
{item}
|
|
19
|
+
</Text>
|
|
20
|
+
);
|
|
21
|
+
// if (typeof item === "string") {
|
|
22
|
+
// return <Text weight="bold">{item}</Text>;
|
|
23
|
+
// } else {
|
|
24
|
+
// return item;
|
|
25
|
+
// }
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
if (selectedItemIndex === undefined && selectedItemIndexes === undefined) {
|
|
29
|
+
console.warn("One of the following must be defined: selectedItemIndex, selectedItemIndexes");
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!multiselect && selectedItemIndexes?.length && selectedItemIndexes?.length > 1) {
|
|
34
|
+
console.warn("Multiple selections not allowed without multiselect flag");
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (selectedItemIndexes?.length && selectedItemIndexes?.length > selectLimit) {
|
|
39
|
+
console.warn("The number of selected items exceeds the limit");
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const isTabActive = (index: any) => {
|
|
44
|
+
return selectedItemIndex === index || selectedItemIndexes?.includes(index)
|
|
45
|
+
? "white"
|
|
46
|
+
: "lightGray";
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Box
|
|
51
|
+
color="lightGray"
|
|
52
|
+
direction="row"
|
|
53
|
+
display="flex"
|
|
54
|
+
height={40}
|
|
55
|
+
justifyContent="between"
|
|
56
|
+
// padding={1}
|
|
57
|
+
rounding={3}
|
|
58
|
+
width="100%"
|
|
59
|
+
>
|
|
60
|
+
{items.map((item, index) => (
|
|
61
|
+
<Box
|
|
62
|
+
key={index}
|
|
63
|
+
color={isTabActive(index)}
|
|
64
|
+
height="100%"
|
|
65
|
+
// paddingX={2}
|
|
66
|
+
rounding={3}
|
|
67
|
+
width={`${100 / items.length}%`}
|
|
68
|
+
>
|
|
69
|
+
<Box
|
|
70
|
+
alignItems="center"
|
|
71
|
+
display="flex"
|
|
72
|
+
height="100%"
|
|
73
|
+
justifyContent="center"
|
|
74
|
+
paddingX={1}
|
|
75
|
+
width="100%"
|
|
76
|
+
onClick={() => {
|
|
77
|
+
if (
|
|
78
|
+
selectedItemIndexes?.length === selectLimit &&
|
|
79
|
+
!selectedItemIndexes?.includes(index)
|
|
80
|
+
) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (multiselect) {
|
|
84
|
+
if (selectedItemIndexes?.includes(index)) {
|
|
85
|
+
onChange({activeIndex: selectedItemIndexes.filter((i) => i !== index)});
|
|
86
|
+
} else {
|
|
87
|
+
const currentIndexes = [...(selectedItemIndexes as number[])];
|
|
88
|
+
currentIndexes?.push(index);
|
|
89
|
+
onChange({activeIndex: currentIndexes?.sort() as number[]});
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
onChange({activeIndex: index});
|
|
93
|
+
}
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
{renderItem(item)}
|
|
97
|
+
</Box>
|
|
98
|
+
</Box>
|
|
99
|
+
))}
|
|
100
|
+
</Box>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {Platform} from "react-native";
|
|
3
|
+
|
|
4
|
+
import {FieldWithLabelsProps, StyleProp} from "./Common";
|
|
5
|
+
import {Icon} from "./Icon";
|
|
6
|
+
import {RNPickerSelect} from "./PickerSelect";
|
|
7
|
+
import {Unifier} from "./Unifier";
|
|
8
|
+
import {WithLabel} from "./WithLabel";
|
|
9
|
+
|
|
10
|
+
// Use "" if you want to have an "unset" value.
|
|
11
|
+
export type SelectListOptions = {label: string; value: string}[];
|
|
12
|
+
export interface SelectListProps extends FieldWithLabelsProps {
|
|
13
|
+
id?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
options: SelectListOptions;
|
|
16
|
+
onChange: (value: string) => void;
|
|
17
|
+
value?: string;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
size?: "md" | "lg";
|
|
20
|
+
// TODO: Implement placeholder prop for Select Field for both Android and iOS
|
|
21
|
+
placeholder?: string;
|
|
22
|
+
style?: StyleProp;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function SelectList({
|
|
26
|
+
options,
|
|
27
|
+
value,
|
|
28
|
+
onChange,
|
|
29
|
+
label,
|
|
30
|
+
labelColor,
|
|
31
|
+
style,
|
|
32
|
+
placeholder,
|
|
33
|
+
disabled,
|
|
34
|
+
}: SelectListProps) {
|
|
35
|
+
const withLabelProps = {label, labelColor};
|
|
36
|
+
|
|
37
|
+
let backgroundColor = style?.backgroundColor || Unifier.theme.white;
|
|
38
|
+
if (disabled) {
|
|
39
|
+
backgroundColor = Unifier.theme.lightGray;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<WithLabel {...withLabelProps}>
|
|
44
|
+
<RNPickerSelect
|
|
45
|
+
Icon={() => {
|
|
46
|
+
// Icon only needed for iOS, web and android use default icons
|
|
47
|
+
return Platform.OS === "ios" ? (
|
|
48
|
+
<Icon color="darkGray" name="angle-down" size="md" />
|
|
49
|
+
) : null;
|
|
50
|
+
}}
|
|
51
|
+
disabled={disabled}
|
|
52
|
+
items={options}
|
|
53
|
+
placeholder={placeholder ? {label: placeholder, value: ""} : {}}
|
|
54
|
+
style={{
|
|
55
|
+
viewContainer: {
|
|
56
|
+
flexDirection: style?.flexDirection || "row",
|
|
57
|
+
justifyContent: style?.justifyContent || "center",
|
|
58
|
+
alignItems: style?.alignItems || "center",
|
|
59
|
+
minHeight: style?.minHeight || 50,
|
|
60
|
+
width: style?.width || "100%",
|
|
61
|
+
borderColor: style?.borderColor || Unifier.theme.gray,
|
|
62
|
+
borderWidth: style?.borderWidth || 1,
|
|
63
|
+
borderRadius: style?.borderRadius || 5,
|
|
64
|
+
backgroundColor,
|
|
65
|
+
},
|
|
66
|
+
inputIOS: {
|
|
67
|
+
paddingVertical: 12,
|
|
68
|
+
paddingHorizontal: 10,
|
|
69
|
+
paddingRight: 30,
|
|
70
|
+
},
|
|
71
|
+
iconContainer: {
|
|
72
|
+
top: 13,
|
|
73
|
+
right: 10,
|
|
74
|
+
bottom: 12,
|
|
75
|
+
paddingLeft: 40,
|
|
76
|
+
},
|
|
77
|
+
inputWeb: {
|
|
78
|
+
// Add padding so the border doesn't mess up layouts
|
|
79
|
+
paddingHorizontal: style?.paddingHorizontal || 6,
|
|
80
|
+
paddingVertical: style?.paddingVertical || 4,
|
|
81
|
+
borderRadius: style?.borderRadius || 5,
|
|
82
|
+
},
|
|
83
|
+
}}
|
|
84
|
+
value={value}
|
|
85
|
+
onValueChange={onChange}
|
|
86
|
+
/>
|
|
87
|
+
</WithLabel>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, {ReactElement} from "react";
|
|
2
|
+
import {Platform, SafeAreaView, StyleProp, ViewStyle} from "react-native";
|
|
3
|
+
import {Drawer} from "react-native-drawer-layout";
|
|
4
|
+
|
|
5
|
+
import {isMobileDevice} from "./MediaQuery";
|
|
6
|
+
|
|
7
|
+
export interface SideDrawerProps {
|
|
8
|
+
// Position of the drawer relative to the child
|
|
9
|
+
position?: "right" | "left";
|
|
10
|
+
// Used to open/hide drawer. Use the onClose and onOpen props to control state
|
|
11
|
+
isOpen: boolean;
|
|
12
|
+
// Content within the drawer
|
|
13
|
+
renderContent: () => ReactElement | ReactElement[];
|
|
14
|
+
// TODO: Allow the hardware back button on Android to close the SideDrawer
|
|
15
|
+
onClose?: () => void;
|
|
16
|
+
onOpen?: () => void;
|
|
17
|
+
drawerType?: "front" | "back" | "slide" | "permanent";
|
|
18
|
+
// Content that is wrapped by the drawer. The drawer will use the height of the child it wraps. Can be overwritten via styles prop
|
|
19
|
+
children?: ReactElement;
|
|
20
|
+
drawerStyles?: StyleProp<ViewStyle>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const DEFAULT_STYLES: StyleProp<ViewStyle> = {
|
|
24
|
+
width: Platform.OS === "web" ? "40%" : "95%",
|
|
25
|
+
backgroundColor: "lightgray",
|
|
26
|
+
borderWidth: 1,
|
|
27
|
+
borderColor: "gray",
|
|
28
|
+
overflow: isMobileDevice() ? undefined : "scroll",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const SideDrawer = ({
|
|
32
|
+
position = "left",
|
|
33
|
+
isOpen,
|
|
34
|
+
renderContent,
|
|
35
|
+
onClose = () => {},
|
|
36
|
+
onOpen = () => {},
|
|
37
|
+
drawerType = "front",
|
|
38
|
+
children,
|
|
39
|
+
drawerStyles = {},
|
|
40
|
+
}: SideDrawerProps): ReactElement => {
|
|
41
|
+
const renderDrawerContent = (): ReactElement => {
|
|
42
|
+
return <SafeAreaView>{renderContent()}</SafeAreaView>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Drawer
|
|
47
|
+
drawerPosition={position}
|
|
48
|
+
drawerStyle={[
|
|
49
|
+
DEFAULT_STYLES,
|
|
50
|
+
drawerStyles,
|
|
51
|
+
{display: Platform.OS === "web" && !isOpen ? "none" : "flex"},
|
|
52
|
+
]}
|
|
53
|
+
drawerType={drawerType}
|
|
54
|
+
open={isOpen}
|
|
55
|
+
renderDrawerContent={renderDrawerContent}
|
|
56
|
+
onClose={onClose}
|
|
57
|
+
onOpen={onOpen}
|
|
58
|
+
>
|
|
59
|
+
{children}
|
|
60
|
+
</Drawer>
|
|
61
|
+
);
|
|
62
|
+
};
|
package/src/Spinner.tsx
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React, {ReactElement, useEffect, useState} from "react";
|
|
2
|
+
import {ActivityIndicator} from "react-native";
|
|
3
|
+
|
|
4
|
+
import {SpinnerProps} from "./Common";
|
|
5
|
+
|
|
6
|
+
export function Spinner({size, color}: SpinnerProps): ReactElement | null {
|
|
7
|
+
const [show, setShow] = useState(false);
|
|
8
|
+
|
|
9
|
+
// The delay is for perceived performance. You don't want to show a spinner when you're doing a quick action.
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const timer = setTimeout(() => setShow(true), 300);
|
|
12
|
+
return () => clearTimeout(timer);
|
|
13
|
+
}, []);
|
|
14
|
+
|
|
15
|
+
if (!show) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const spinnerSize: "small" | "large" = size === "sm" ? "small" : "large";
|
|
19
|
+
return <ActivityIndicator color={color || "darkGray"} size={spinnerSize} />;
|
|
20
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// TODO: Update SplitPage native to have desktop UX for tablet sized screens
|
|
2
|
+
import React, {useCallback, useEffect, useState} from "react";
|
|
3
|
+
import flattenChildren from "react-keyed-flatten-children";
|
|
4
|
+
import {Dimensions, ListRenderItemInfo, View} from "react-native";
|
|
5
|
+
import {SwiperFlatList} from "react-native-swiper-flatlist";
|
|
6
|
+
|
|
7
|
+
import {Box} from "./Box";
|
|
8
|
+
import {SplitPageProps} from "./Common";
|
|
9
|
+
import {FlatList} from "./FlatList";
|
|
10
|
+
import {IconButton} from "./IconButton";
|
|
11
|
+
import {Spinner} from "./Spinner";
|
|
12
|
+
import {Unifier} from "./Unifier";
|
|
13
|
+
|
|
14
|
+
export const SplitPage = ({
|
|
15
|
+
children,
|
|
16
|
+
loading = false,
|
|
17
|
+
color,
|
|
18
|
+
keyboardOffset,
|
|
19
|
+
renderListViewItem,
|
|
20
|
+
renderListViewHeader,
|
|
21
|
+
renderContent,
|
|
22
|
+
onSelectionChange = () => {},
|
|
23
|
+
listViewData,
|
|
24
|
+
listViewExtraData,
|
|
25
|
+
bottomNavBarHeight,
|
|
26
|
+
showItemList,
|
|
27
|
+
}: SplitPageProps) => {
|
|
28
|
+
const [selectedId, setSelectedId] = useState<number | undefined>(undefined);
|
|
29
|
+
|
|
30
|
+
// flattenChildren is necessary to pull children from a React Fragment. Without this,
|
|
31
|
+
// splitPage would only recognize the fragment container instead stripping it to render
|
|
32
|
+
// the children individually
|
|
33
|
+
const elementArray = flattenChildren(children);
|
|
34
|
+
const {width} = Dimensions.get("window");
|
|
35
|
+
|
|
36
|
+
const onItemSelect = useCallback(
|
|
37
|
+
(item: ListRenderItemInfo<any>) => {
|
|
38
|
+
setSelectedId(item.index);
|
|
39
|
+
onSelectionChange(item);
|
|
40
|
+
},
|
|
41
|
+
[onSelectionChange]
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const onItemDeselect = useCallback(() => {
|
|
45
|
+
setSelectedId(undefined);
|
|
46
|
+
onSelectionChange(undefined);
|
|
47
|
+
}, [onSelectionChange]);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (showItemList) {
|
|
51
|
+
onItemDeselect();
|
|
52
|
+
}
|
|
53
|
+
}, [showItemList, onItemDeselect]);
|
|
54
|
+
|
|
55
|
+
if (!children && !renderContent) {
|
|
56
|
+
console.warn("A child node is required");
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const renderItem = (itemInfo: ListRenderItemInfo<any>) => {
|
|
61
|
+
return (
|
|
62
|
+
<Box
|
|
63
|
+
onClick={() => {
|
|
64
|
+
Unifier.utils.haptic();
|
|
65
|
+
onItemSelect(itemInfo);
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
{renderListViewItem(itemInfo)}
|
|
69
|
+
</Box>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const renderList = () => {
|
|
74
|
+
if (selectedId !== undefined) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<View
|
|
80
|
+
style={{
|
|
81
|
+
width: "100%",
|
|
82
|
+
maxWidth: "100%",
|
|
83
|
+
flexGrow: 1,
|
|
84
|
+
flexShrink: 0,
|
|
85
|
+
display: "flex",
|
|
86
|
+
flexDirection: "column",
|
|
87
|
+
paddingBottom: bottomNavBarHeight,
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
{renderListViewHeader && renderListViewHeader()}
|
|
91
|
+
<FlatList
|
|
92
|
+
data={listViewData}
|
|
93
|
+
extraData={listViewExtraData}
|
|
94
|
+
keyExtractor={(item) => item.id}
|
|
95
|
+
renderItem={renderItem}
|
|
96
|
+
/>
|
|
97
|
+
</View>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const renderListContent = () => {
|
|
102
|
+
if (selectedId === undefined) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return (
|
|
106
|
+
<Box flex="grow" padding={2}>
|
|
107
|
+
<Box width="100%">
|
|
108
|
+
<IconButton
|
|
109
|
+
accessibilityLabel="close"
|
|
110
|
+
icon="times"
|
|
111
|
+
iconColor="darkGray"
|
|
112
|
+
onClick={() => onItemDeselect()}
|
|
113
|
+
/>
|
|
114
|
+
</Box>
|
|
115
|
+
{renderContent && renderContent(selectedId)}
|
|
116
|
+
</Box>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const renderChildrenContent = () => {
|
|
121
|
+
if (selectedId === undefined) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return (
|
|
125
|
+
<SwiperFlatList
|
|
126
|
+
nestedScrollEnabled
|
|
127
|
+
renderAll
|
|
128
|
+
showPagination={elementArray.length > 1}
|
|
129
|
+
style={{width: "100%"}}
|
|
130
|
+
>
|
|
131
|
+
{elementArray.map((element, i) => {
|
|
132
|
+
return (
|
|
133
|
+
<View
|
|
134
|
+
key={i}
|
|
135
|
+
style={{width, height: elementArray.length > 1 ? "95%" : "100%", padding: 4}}
|
|
136
|
+
>
|
|
137
|
+
{element}
|
|
138
|
+
</View>
|
|
139
|
+
);
|
|
140
|
+
})}
|
|
141
|
+
</SwiperFlatList>
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const renderMainContent = renderContent ? renderListContent() : renderChildrenContent();
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<Box
|
|
149
|
+
avoidKeyboard
|
|
150
|
+
color={color || "lightGray"}
|
|
151
|
+
flex="grow"
|
|
152
|
+
height="100%"
|
|
153
|
+
keyboardOffset={keyboardOffset}
|
|
154
|
+
width="100%"
|
|
155
|
+
>
|
|
156
|
+
{loading === true && <Spinner color={Unifier.theme.darkGray as any} size="md" />}
|
|
157
|
+
{selectedId === undefined ? renderList() : renderMainContent}
|
|
158
|
+
</Box>
|
|
159
|
+
);
|
|
160
|
+
};
|