ferns-ui 0.26.0 → 0.26.1
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/ActionSheet.d.ts +1 -1
- package/dist/ActionSheet.js +1 -2
- package/dist/ActionSheet.js.map +1 -1
- package/dist/CheckBox.d.ts +1 -4
- package/dist/CheckBox.js +33 -20
- package/dist/CheckBox.js.map +1 -1
- package/dist/Common.d.ts +44 -10
- package/dist/Common.js.map +1 -1
- package/dist/DateTimeField.android.d.ts +1 -1
- package/dist/DateTimeField.android.js +58 -16
- package/dist/DateTimeField.android.js.map +1 -1
- package/dist/DateTimeField.d.ts +2 -2
- package/dist/DateTimeField.ios.d.ts +1 -1
- package/dist/DateTimeField.ios.js +43 -12
- package/dist/DateTimeField.ios.js.map +1 -1
- package/dist/DateTimeField.js.map +1 -1
- package/dist/Field.js +2 -2
- package/dist/Field.js.map +1 -1
- package/dist/Mask.d.ts +2 -3
- package/dist/MediaQuery.d.ts +1 -0
- package/dist/MediaQuery.js +16 -0
- package/dist/MediaQuery.js.map +1 -1
- package/dist/Page.js.map +1 -1
- package/dist/SegmentedControl.js +6 -2
- package/dist/SegmentedControl.js.map +1 -1
- package/dist/SelectList.d.ts +1 -1
- package/dist/SelectList.js +9 -8
- package/dist/SelectList.js.map +1 -1
- package/dist/SplitPage.d.ts +3 -21
- package/dist/SplitPage.js +78 -23
- package/dist/SplitPage.js.map +1 -1
- package/dist/SplitPage.native.d.ts +3 -0
- package/dist/SplitPage.native.js +75 -0
- package/dist/SplitPage.native.js.map +1 -0
- package/dist/TapToEdit.js +11 -17
- package/dist/TapToEdit.js.map +1 -1
- package/dist/TextField.js +11 -6
- package/dist/TextField.js.map +1 -1
- package/dist/Utilities.d.ts +1 -0
- package/dist/Utilities.js +18 -2
- package/dist/Utilities.js.map +1 -1
- package/dist/WithLabel.d.ts +3 -3
- package/dist/WithLabel.js +3 -0
- package/dist/WithLabel.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/ActionSheet.tsx +2 -3
- package/src/CheckBox.tsx +85 -60
- package/src/Common.ts +49 -10
- package/src/DateTimeField.android.tsx +71 -26
- package/src/DateTimeField.ios.tsx +55 -13
- package/src/DateTimeField.tsx +2 -2
- package/src/Field.tsx +4 -4
- package/src/Mask.tsx +2 -2
- package/src/MediaQuery.ts +14 -0
- package/src/Page.tsx +0 -1
- package/src/SegmentedControl.tsx +3 -3
- package/src/SelectList.tsx +9 -2
- package/src/SplitPage.native.tsx +156 -0
- package/src/SplitPage.tsx +136 -47
- package/src/TapToEdit.tsx +9 -22
- package/src/TextField.tsx +26 -17
- package/src/Utilities.tsx +24 -3
- package/src/WithLabel.tsx +6 -3
- package/src/index.tsx +6 -5
package/src/SplitPage.tsx
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, {Children,
|
|
2
|
-
import {ListRenderItemInfo, ScrollView, View} from "react-native";
|
|
1
|
+
import React, {Children, useCallback, useEffect, useState} from "react";
|
|
2
|
+
import {Dimensions, ListRenderItemInfo, ScrollView, View} from "react-native";
|
|
3
|
+
import {SwiperFlatList} from "react-native-swiper-flatlist";
|
|
3
4
|
|
|
4
5
|
import {Box} from "./Box";
|
|
5
|
-
import {
|
|
6
|
+
import {SplitPageProps} from "./Common";
|
|
6
7
|
import {FlatList} from "./FlatList";
|
|
7
8
|
import {IconButton} from "./IconButton";
|
|
8
9
|
import {mediaQueryLargerThan} from "./MediaQuery";
|
|
@@ -10,24 +11,6 @@ import {SegmentedControl} from "./SegmentedControl";
|
|
|
10
11
|
import {Spinner} from "./Spinner";
|
|
11
12
|
import {Unifier} from "./Unifier";
|
|
12
13
|
|
|
13
|
-
interface SplitPageProps {
|
|
14
|
-
children?: ReactChild | ReactChild[] | null;
|
|
15
|
-
tabs?: string[];
|
|
16
|
-
// TODO: figure out navigation
|
|
17
|
-
navigation?: any;
|
|
18
|
-
loading?: boolean;
|
|
19
|
-
color?: Color;
|
|
20
|
-
keyboardOffset?: number;
|
|
21
|
-
renderListViewItem: (itemInfo: ListRenderItemInfo<any>) => ReactElement | null;
|
|
22
|
-
renderListViewHeader?: () => ReactElement | null;
|
|
23
|
-
renderContent?: (index?: number) => ReactElement | ReactElement[] | null;
|
|
24
|
-
listViewData: any[];
|
|
25
|
-
listViewExtraData?: any;
|
|
26
|
-
listViewWidth?: number;
|
|
27
|
-
renderChild?: () => ReactChild;
|
|
28
|
-
selectLimit?: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
14
|
// A component for rendering a list on one side and a details view on the right for large screens,
|
|
32
15
|
// and a scrollable list where clicking an item takes you the details view.
|
|
33
16
|
export const SplitPage = ({
|
|
@@ -39,16 +22,41 @@ export const SplitPage = ({
|
|
|
39
22
|
renderListViewItem,
|
|
40
23
|
renderListViewHeader,
|
|
41
24
|
renderContent,
|
|
25
|
+
onSelectionChange = () => {},
|
|
42
26
|
listViewData,
|
|
43
27
|
listViewExtraData,
|
|
44
28
|
listViewWidth,
|
|
29
|
+
bottomNavBarHeight,
|
|
30
|
+
showItemList,
|
|
45
31
|
selectLimit,
|
|
46
32
|
}: SplitPageProps) => {
|
|
47
33
|
const [selectedId, setSelectedId] = useState<number | undefined>(undefined);
|
|
48
34
|
const [activeTabs, setActiveTabs] = useState<number[]>(tabs.length > 2 ? [0, 1] : []);
|
|
35
|
+
const {width} = Dimensions.get("window");
|
|
36
|
+
|
|
37
|
+
const isMobileDevice = !mediaQueryLargerThan("sm");
|
|
49
38
|
|
|
50
39
|
const elementArray = Children.toArray(children);
|
|
51
40
|
|
|
41
|
+
const onItemSelect = useCallback(
|
|
42
|
+
(item: ListRenderItemInfo<any>) => {
|
|
43
|
+
setSelectedId(item.index);
|
|
44
|
+
onSelectionChange(item);
|
|
45
|
+
},
|
|
46
|
+
[onSelectionChange]
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const onItemDeselect = useCallback(() => {
|
|
50
|
+
setSelectedId(undefined);
|
|
51
|
+
onSelectionChange(undefined);
|
|
52
|
+
}, [onSelectionChange]);
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (showItemList) {
|
|
56
|
+
onItemDeselect();
|
|
57
|
+
}
|
|
58
|
+
}, [showItemList, onItemDeselect]);
|
|
59
|
+
|
|
52
60
|
if (!children && !renderContent) {
|
|
53
61
|
console.warn("A child node is required");
|
|
54
62
|
return null;
|
|
@@ -63,7 +71,7 @@ export const SplitPage = ({
|
|
|
63
71
|
return (
|
|
64
72
|
<Box
|
|
65
73
|
onClick={() => {
|
|
66
|
-
|
|
74
|
+
onItemSelect(itemInfo);
|
|
67
75
|
}}
|
|
68
76
|
>
|
|
69
77
|
{renderListViewItem(itemInfo)}
|
|
@@ -72,19 +80,14 @@ export const SplitPage = ({
|
|
|
72
80
|
};
|
|
73
81
|
|
|
74
82
|
const renderList = () => {
|
|
75
|
-
if (!mediaQueryLargerThan("sm") && selectedId) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
83
|
return (
|
|
79
84
|
<View
|
|
80
85
|
style={{
|
|
81
|
-
width:
|
|
82
|
-
maxWidth:
|
|
86
|
+
width: listViewWidth ?? 300,
|
|
87
|
+
maxWidth: listViewWidth ?? 300,
|
|
83
88
|
flexGrow: 1,
|
|
84
89
|
flexShrink: 0,
|
|
85
90
|
display: "flex",
|
|
86
|
-
paddingTop: "12px",
|
|
87
|
-
paddingBottom: "12px",
|
|
88
91
|
flexDirection: "column",
|
|
89
92
|
}}
|
|
90
93
|
>
|
|
@@ -102,16 +105,6 @@ export const SplitPage = ({
|
|
|
102
105
|
const renderListContent = () => {
|
|
103
106
|
return (
|
|
104
107
|
<Box flex="grow" padding={2}>
|
|
105
|
-
{!mediaQueryLargerThan("sm") && (
|
|
106
|
-
<Box width="100%">
|
|
107
|
-
<IconButton
|
|
108
|
-
accessibilityLabel="close"
|
|
109
|
-
icon="times"
|
|
110
|
-
iconColor="darkGray"
|
|
111
|
-
onClick={() => setSelectedId(undefined)}
|
|
112
|
-
/>
|
|
113
|
-
</Box>
|
|
114
|
-
)}
|
|
115
108
|
{renderContent && renderContent(selectedId)}
|
|
116
109
|
</Box>
|
|
117
110
|
);
|
|
@@ -128,7 +121,7 @@ export const SplitPage = ({
|
|
|
128
121
|
alignItems: "center",
|
|
129
122
|
}}
|
|
130
123
|
>
|
|
131
|
-
<Box
|
|
124
|
+
<Box marginBottom={4} paddingX={4} width="100%">
|
|
132
125
|
<SegmentedControl
|
|
133
126
|
items={tabs}
|
|
134
127
|
multiselect
|
|
@@ -143,10 +136,10 @@ export const SplitPage = ({
|
|
|
143
136
|
direction="row"
|
|
144
137
|
flex="grow"
|
|
145
138
|
height="100%"
|
|
146
|
-
paddingX={
|
|
139
|
+
paddingX={4}
|
|
147
140
|
width={activeTabs.length > 1 ? "100%" : "60%"}
|
|
148
141
|
>
|
|
149
|
-
{activeTabs.map((tabIndex) => {
|
|
142
|
+
{activeTabs.map((tabIndex, i) => {
|
|
150
143
|
return (
|
|
151
144
|
<ScrollView
|
|
152
145
|
key={tabIndex}
|
|
@@ -156,8 +149,9 @@ export const SplitPage = ({
|
|
|
156
149
|
style={{
|
|
157
150
|
flex: 1,
|
|
158
151
|
width: "60%",
|
|
159
|
-
padding: 3 * SPACING,
|
|
160
152
|
height: "100%",
|
|
153
|
+
paddingRight: i ? 0 : 16,
|
|
154
|
+
paddingLeft: i ? 16 : 0,
|
|
161
155
|
}}
|
|
162
156
|
>
|
|
163
157
|
{elementArray[tabIndex]}
|
|
@@ -180,7 +174,6 @@ export const SplitPage = ({
|
|
|
180
174
|
style={{
|
|
181
175
|
flex: 1,
|
|
182
176
|
width: "60%",
|
|
183
|
-
padding: 3 * SPACING,
|
|
184
177
|
height: "100%",
|
|
185
178
|
}}
|
|
186
179
|
>
|
|
@@ -193,21 +186,117 @@ export const SplitPage = ({
|
|
|
193
186
|
}
|
|
194
187
|
};
|
|
195
188
|
|
|
189
|
+
const renderMobileList = () => {
|
|
190
|
+
if (isMobileDevice && selectedId !== undefined) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<View
|
|
196
|
+
style={{
|
|
197
|
+
width: "100%",
|
|
198
|
+
maxWidth: "100%",
|
|
199
|
+
height: "100%",
|
|
200
|
+
flexGrow: 1,
|
|
201
|
+
flexShrink: 0,
|
|
202
|
+
display: "flex",
|
|
203
|
+
flexDirection: "column",
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
{renderListViewHeader && renderListViewHeader()}
|
|
207
|
+
<FlatList
|
|
208
|
+
data={listViewData}
|
|
209
|
+
extraData={listViewExtraData}
|
|
210
|
+
keyExtractor={(item) => item.id}
|
|
211
|
+
nestedScrollEnabled
|
|
212
|
+
renderItem={renderItem}
|
|
213
|
+
/>
|
|
214
|
+
</View>
|
|
215
|
+
);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const renderMobileListContent = () => {
|
|
219
|
+
if (isMobileDevice && selectedId === undefined) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<Box flex="grow" padding={2}>
|
|
225
|
+
{isMobileDevice && (
|
|
226
|
+
<Box width="100%">
|
|
227
|
+
<IconButton
|
|
228
|
+
accessibilityLabel="close"
|
|
229
|
+
icon="times"
|
|
230
|
+
iconColor="darkGray"
|
|
231
|
+
onClick={() => onItemDeselect()}
|
|
232
|
+
/>
|
|
233
|
+
</Box>
|
|
234
|
+
)}
|
|
235
|
+
{renderContent && renderContent(selectedId)}
|
|
236
|
+
</Box>
|
|
237
|
+
);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const renderMobileChildrenContent = () => {
|
|
241
|
+
if (selectedId === undefined) {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return (
|
|
245
|
+
<SwiperFlatList
|
|
246
|
+
nestedScrollEnabled
|
|
247
|
+
paginationStyle={{justifyContent: "center", width: "95%"}}
|
|
248
|
+
renderAll
|
|
249
|
+
showPagination
|
|
250
|
+
style={{width: "100%"}}
|
|
251
|
+
>
|
|
252
|
+
{elementArray.map((element, i) => {
|
|
253
|
+
return (
|
|
254
|
+
<View
|
|
255
|
+
key={i}
|
|
256
|
+
style={{
|
|
257
|
+
width: width - 8,
|
|
258
|
+
padding: 4,
|
|
259
|
+
height: elementArray.length > 1 ? "90vh" : "100vh",
|
|
260
|
+
paddingBottom: bottomNavBarHeight,
|
|
261
|
+
}}
|
|
262
|
+
>
|
|
263
|
+
{element}
|
|
264
|
+
</View>
|
|
265
|
+
);
|
|
266
|
+
})}
|
|
267
|
+
</SwiperFlatList>
|
|
268
|
+
);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const renderSplitPage = () => {
|
|
272
|
+
return (
|
|
273
|
+
<>
|
|
274
|
+
{renderList()}
|
|
275
|
+
{renderContent ? renderListContent() : renderChildrenContent()}
|
|
276
|
+
</>
|
|
277
|
+
);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const renderMobileSplitPage = () => {
|
|
281
|
+
const renderMainContent = renderContent
|
|
282
|
+
? renderMobileListContent()
|
|
283
|
+
: renderMobileChildrenContent();
|
|
284
|
+
return selectedId === undefined ? renderMobileList() : renderMainContent;
|
|
285
|
+
};
|
|
286
|
+
|
|
196
287
|
return (
|
|
197
288
|
<Box
|
|
198
289
|
avoidKeyboard
|
|
199
290
|
color={color || "lightGray"}
|
|
200
291
|
direction="row"
|
|
201
292
|
display="flex"
|
|
202
|
-
flex="grow"
|
|
203
293
|
height="100%"
|
|
204
294
|
keyboardOffset={keyboardOffset}
|
|
205
295
|
padding={2}
|
|
206
296
|
width="100%"
|
|
207
297
|
>
|
|
208
298
|
{loading === true && <Spinner color={Unifier.theme.darkGray as any} size="md" />}
|
|
209
|
-
{
|
|
210
|
-
{renderContent ? renderListContent() : renderChildrenContent()}
|
|
299
|
+
{Boolean(isMobileDevice) ? renderMobileSplitPage() : renderSplitPage()}
|
|
211
300
|
</Box>
|
|
212
301
|
);
|
|
213
302
|
};
|
package/src/TapToEdit.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import {BoxProps} from "./Common";
|
|
|
7
7
|
import {Field, FieldProps} from "./Field";
|
|
8
8
|
import {Icon} from "./Icon";
|
|
9
9
|
import {Text} from "./Text";
|
|
10
|
+
import {formatAddress} from "./Utilities";
|
|
10
11
|
|
|
11
12
|
export interface TapToEditProps extends Omit<FieldProps, "onChange" | "value"> {
|
|
12
13
|
title: string;
|
|
@@ -113,29 +114,15 @@ export const TapToEdit = ({
|
|
|
113
114
|
displayValue = value.join(", ");
|
|
114
115
|
} else if (fieldProps?.type === "url") {
|
|
115
116
|
// Show only the domain, full links are likely too long.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
let state = "";
|
|
125
|
-
if (value?.state) {
|
|
126
|
-
state = value?.zipcode ? `${value.state} ` : `${value.state}`;
|
|
117
|
+
try {
|
|
118
|
+
const url = new URL(value);
|
|
119
|
+
displayValue = url?.hostname ?? value;
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.debug(`Invalid URL: ${value}`);
|
|
122
|
+
displayValue = value;
|
|
127
123
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const addressLineOne = value?.address1 ?? "";
|
|
132
|
-
const addressLineTwo = value?.address2 ?? "";
|
|
133
|
-
const addressLineThree = `${city}${state}${zip}`;
|
|
134
|
-
|
|
135
|
-
// Only add new lines if lines before and after are not empty to avoid awkward whitespace
|
|
136
|
-
displayValue = `${addressLineOne}${
|
|
137
|
-
addressLineOne && (addressLineTwo || addressLineThree) ? `\n` : ""
|
|
138
|
-
}${addressLineTwo}${addressLineTwo && addressLineThree ? `\n` : ""}${addressLineThree}`;
|
|
124
|
+
} else if (fieldProps?.type === "address") {
|
|
125
|
+
displayValue = formatAddress(value);
|
|
139
126
|
}
|
|
140
127
|
}
|
|
141
128
|
|
package/src/TextField.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {AsYouType} from "libphonenumber-js";
|
|
2
2
|
import moment from "moment-timezone";
|
|
3
|
-
import React, {ReactElement, useState} from "react";
|
|
3
|
+
import React, {ReactElement, useCallback, useMemo, useState} from "react";
|
|
4
4
|
import {ActivityIndicator, KeyboardTypeOptions, Platform, TextInput, View} from "react-native";
|
|
5
5
|
import {Calendar} from "react-native-calendars";
|
|
6
6
|
|
|
@@ -168,7 +168,7 @@ export function TextField({
|
|
|
168
168
|
borderColor = Unifier.theme.gray;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
const getHeight = () => {
|
|
171
|
+
const getHeight = useCallback(() => {
|
|
172
172
|
if (grow) {
|
|
173
173
|
return Math.max(40, height);
|
|
174
174
|
} else if (multiline) {
|
|
@@ -176,7 +176,29 @@ export function TextField({
|
|
|
176
176
|
} else {
|
|
177
177
|
return 40;
|
|
178
178
|
}
|
|
179
|
-
};
|
|
179
|
+
}, [grow, height, multiline]);
|
|
180
|
+
|
|
181
|
+
const defaultTextInputStyles = useMemo(() => {
|
|
182
|
+
const defaultStyles = {
|
|
183
|
+
flex: 1,
|
|
184
|
+
paddingTop: 10,
|
|
185
|
+
paddingRight: 10,
|
|
186
|
+
paddingBottom: 10,
|
|
187
|
+
paddingLeft: 0,
|
|
188
|
+
height: getHeight(),
|
|
189
|
+
width: "100%",
|
|
190
|
+
color: Unifier.theme.darkGray,
|
|
191
|
+
fontFamily: Unifier.theme.primaryFont,
|
|
192
|
+
...style,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
if (Platform.OS === "web") {
|
|
196
|
+
defaultStyles.outline = 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return defaultStyles;
|
|
200
|
+
}, [getHeight, style]);
|
|
201
|
+
|
|
180
202
|
const isHandledByModal =
|
|
181
203
|
type === "date" || type === "numberRange" || type === "decimalRange" || type === "height";
|
|
182
204
|
|
|
@@ -269,20 +291,7 @@ export function TextField({
|
|
|
269
291
|
placeholderTextColor={Unifier.theme.gray}
|
|
270
292
|
returnKeyType={type === "number" || type === "decimal" ? "done" : returnKeyType}
|
|
271
293
|
secureTextEntry={type === "password"}
|
|
272
|
-
style={
|
|
273
|
-
flex: 1,
|
|
274
|
-
paddingTop: 10,
|
|
275
|
-
paddingRight: 10,
|
|
276
|
-
paddingBottom: 10,
|
|
277
|
-
paddingLeft: 0,
|
|
278
|
-
height: getHeight(),
|
|
279
|
-
width: "100%",
|
|
280
|
-
color: Unifier.theme.darkGray,
|
|
281
|
-
fontFamily: Unifier.theme.primaryFont,
|
|
282
|
-
// Remove border in web.
|
|
283
|
-
outlineWidth: 0,
|
|
284
|
-
...style,
|
|
285
|
-
}}
|
|
294
|
+
style={defaultTextInputStyles}
|
|
286
295
|
// For react-native-autofocus
|
|
287
296
|
textContentType={textContentType}
|
|
288
297
|
underlineColorAndroid="transparent"
|
package/src/Utilities.tsx
CHANGED
|
@@ -4,14 +4,12 @@ import get from "lodash/get";
|
|
|
4
4
|
|
|
5
5
|
export function mergeInlineStyles(inlineStyle?: any, newStyle?: any) {
|
|
6
6
|
const inline = get(inlineStyle, "__style");
|
|
7
|
-
|
|
7
|
+
return {
|
|
8
8
|
__style: {
|
|
9
9
|
...inline,
|
|
10
10
|
...newStyle,
|
|
11
11
|
},
|
|
12
12
|
};
|
|
13
|
-
|
|
14
|
-
return dangerouslySetInlineStyle;
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
/*
|
|
@@ -159,3 +157,26 @@ export const union =
|
|
|
159
157
|
<T,>(...fns: Functor<T>[]) =>
|
|
160
158
|
(val: T) =>
|
|
161
159
|
concat(fns.map((fn) => fn(val)));
|
|
160
|
+
|
|
161
|
+
export function formatAddress(address: any): string {
|
|
162
|
+
let city = "";
|
|
163
|
+
if (address?.city) {
|
|
164
|
+
city = address?.state || address.zipcode ? `${address.city}, ` : `${address.city}`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let state = "";
|
|
168
|
+
if (address?.state) {
|
|
169
|
+
state = address?.zipcode ? `${address.state} ` : `${address.state}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const zip = address?.zipcode || "";
|
|
173
|
+
|
|
174
|
+
const addressLineOne = address?.address1 ?? "";
|
|
175
|
+
const addressLineTwo = address?.address2 ?? "";
|
|
176
|
+
const addressLineThree = `${city}${state}${zip}`;
|
|
177
|
+
|
|
178
|
+
// Only add new lines if lines before and after are not empty to avoid awkward whitespace
|
|
179
|
+
return `${addressLineOne}${
|
|
180
|
+
addressLineOne && (addressLineTwo || addressLineThree) ? `\n` : ""
|
|
181
|
+
}${addressLineTwo}${addressLineTwo && addressLineThree ? `\n` : ""}${addressLineThree}`;
|
|
182
|
+
}
|
package/src/WithLabel.tsx
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import {Box} from "./Box";
|
|
4
|
-
import {AllColors, JustifyContent, TextSize} from "./Common";
|
|
4
|
+
import {AllColors, JustifyContent, ReactChildren, TextSize} from "./Common";
|
|
5
5
|
import {Text} from "./Text";
|
|
6
6
|
|
|
7
7
|
export interface WithLabelProps {
|
|
8
|
-
children
|
|
8
|
+
children?: ReactChildren;
|
|
9
9
|
show?: boolean;
|
|
10
10
|
label?: string;
|
|
11
11
|
labelInline?: boolean;
|
|
@@ -24,7 +24,10 @@ export function WithLabel({
|
|
|
24
24
|
labelColor,
|
|
25
25
|
show,
|
|
26
26
|
children,
|
|
27
|
-
}: WithLabelProps) {
|
|
27
|
+
}: WithLabelProps): React.ReactElement | null {
|
|
28
|
+
if (!children) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
28
31
|
return (
|
|
29
32
|
<Box
|
|
30
33
|
direction={labelInline ? "row" : "column"}
|
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./Constants";
|
|
2
2
|
export * from "./Common";
|
|
3
|
+
export * from "./MediaQuery";
|
|
3
4
|
export * from "./ActionSheet";
|
|
4
5
|
export * from "./Avatar";
|
|
5
6
|
export * from "./Badge";
|
|
@@ -69,7 +70,7 @@ interface Insets {
|
|
|
69
70
|
right?: number;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
// Lifted from react-native-
|
|
73
|
+
// Lifted from react-native-navigation
|
|
73
74
|
// import {Options} from "./Options";
|
|
74
75
|
export interface LayoutComponent<P = {}> {
|
|
75
76
|
/**
|
|
@@ -453,7 +454,7 @@ export interface OptionsTopBarTitle {
|
|
|
453
454
|
passProps?: object;
|
|
454
455
|
};
|
|
455
456
|
/**
|
|
456
|
-
* Top Bar title height in
|
|
457
|
+
* Top Bar title height in density pixels
|
|
457
458
|
* #### (Android specific)
|
|
458
459
|
*/
|
|
459
460
|
height?: number;
|
|
@@ -496,7 +497,7 @@ export interface OptionsTopBarBackButton {
|
|
|
496
497
|
*/
|
|
497
498
|
icon?: ImageRequireSource;
|
|
498
499
|
/**
|
|
499
|
-
*
|
|
500
|
+
* Whether the back button is visible or not
|
|
500
501
|
* @default true
|
|
501
502
|
*/
|
|
502
503
|
visible?: boolean;
|
|
@@ -1005,14 +1006,14 @@ export interface OverlayOptions {
|
|
|
1005
1006
|
*/
|
|
1006
1007
|
interceptTouchOutside?: boolean;
|
|
1007
1008
|
/**
|
|
1008
|
-
* Control
|
|
1009
|
+
* Control whether this Overlay should handle Keyboard events.
|
|
1009
1010
|
* Set this to true if your Overlay contains a TextInput.
|
|
1010
1011
|
*/
|
|
1011
1012
|
handleKeyboardEvents?: boolean;
|
|
1012
1013
|
}
|
|
1013
1014
|
export interface ModalOptions {
|
|
1014
1015
|
/**
|
|
1015
|
-
* Control
|
|
1016
|
+
* Control whether this modal should be dismiss using swipe gesture when the modalPresentationStyle = 'pageSheet'
|
|
1016
1017
|
* #### (iOS specific)
|
|
1017
1018
|
*/
|
|
1018
1019
|
swipeToDismiss?: boolean;
|