ferns-ui 1.0.0-beta.0 → 1.0.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/Accordion.js +15 -8
- package/dist/Accordion.js.map +1 -1
- package/dist/Badge.d.ts +1 -1
- package/dist/Badge.js +10 -5
- package/dist/Badge.js.map +1 -1
- package/dist/Button.js +3 -3
- package/dist/Common.d.ts +65 -13
- package/dist/Common.js.map +1 -1
- package/dist/DateTimeActionSheet.js +1 -1
- package/dist/DateTimeActionSheet.js.map +1 -1
- package/dist/DateTimeField.js +4 -4
- package/dist/DateTimeField.js.map +1 -1
- package/dist/Field.js +1 -1
- package/dist/Field.js.map +1 -1
- package/dist/IconButton.js +3 -3
- package/dist/Modal.js +5 -5
- package/dist/Page.js +1 -1
- package/dist/Page.js.map +1 -1
- package/dist/SegmentedControl.js +3 -2
- package/dist/SegmentedControl.js.map +1 -1
- package/dist/SelectField.js +2 -2
- package/dist/SelectField.js.map +1 -1
- package/dist/TapToEdit.d.ts +1 -1
- package/dist/TapToEdit.js +43 -42
- package/dist/TapToEdit.js.map +1 -1
- package/dist/Tooltip.js +26 -29
- package/dist/Tooltip.js.map +1 -1
- package/package.json +1 -1
- package/src/Accordion.tsx +28 -20
- package/src/Badge.tsx +18 -8
- package/src/Button.tsx +4 -4
- package/src/Common.ts +79 -20
- package/src/DateTimeActionSheet.tsx +1 -1
- package/src/DateTimeField.tsx +4 -4
- package/src/Field.tsx +6 -1
- package/src/IconButton.tsx +4 -4
- package/src/Modal.tsx +8 -8
- package/src/Page.tsx +1 -1
- package/src/SegmentedControl.tsx +3 -2
- package/src/SelectField.tsx +2 -2
- package/src/TapToEdit.tsx +73 -95
- package/src/Tooltip.tsx +52 -58
package/src/Common.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface AccordionProps {
|
|
|
31
31
|
/**
|
|
32
32
|
* The subtitle of the information modal.
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
infoModalSubtitle?: ModalProps["subtitle"];
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* The text content of the information modal.
|
|
@@ -49,6 +49,11 @@ export interface AccordionProps {
|
|
|
49
49
|
*/
|
|
50
50
|
isCollapsed?: boolean;
|
|
51
51
|
|
|
52
|
+
/*
|
|
53
|
+
* The subtitle showed below the title of the accordion.
|
|
54
|
+
*/
|
|
55
|
+
subtitle?: string;
|
|
56
|
+
|
|
52
57
|
/**
|
|
53
58
|
* The title of the accordion.
|
|
54
59
|
*/
|
|
@@ -1296,6 +1301,26 @@ export interface AvatarProps {
|
|
|
1296
1301
|
}
|
|
1297
1302
|
|
|
1298
1303
|
export interface BadgeProps {
|
|
1304
|
+
/**
|
|
1305
|
+
* When status is "custom", determines the badge's background color.
|
|
1306
|
+
*/
|
|
1307
|
+
customBackgroundColor?: string;
|
|
1308
|
+
/**
|
|
1309
|
+
* When status is "custom", determines the badge's border color.
|
|
1310
|
+
*/
|
|
1311
|
+
customBorderColor?: string;
|
|
1312
|
+
/**
|
|
1313
|
+
* When status is "custom", determines the badge's icon color
|
|
1314
|
+
*/
|
|
1315
|
+
customIconColor?: IconColor;
|
|
1316
|
+
/**
|
|
1317
|
+
* When status is "custom", determines the badge's icon
|
|
1318
|
+
*/
|
|
1319
|
+
customIconName?: IconName;
|
|
1320
|
+
/**
|
|
1321
|
+
* When status is "custom", determines the badge's text color.
|
|
1322
|
+
*/
|
|
1323
|
+
customTextColor?: string;
|
|
1299
1324
|
/**
|
|
1300
1325
|
* The name of the icon to display in the badge.
|
|
1301
1326
|
*/
|
|
@@ -1320,7 +1345,7 @@ export interface BadgeProps {
|
|
|
1320
1345
|
* The status of the badge. Determines its color and appearance.
|
|
1321
1346
|
* @default "info"
|
|
1322
1347
|
*/
|
|
1323
|
-
status?: "info" | "error" | "warning" | "success" | "neutral";
|
|
1348
|
+
status?: "info" | "error" | "warning" | "success" | "neutral" | "custom";
|
|
1324
1349
|
|
|
1325
1350
|
/**
|
|
1326
1351
|
* The text or number to display inside the badge.
|
|
@@ -1711,7 +1736,7 @@ export interface ModalProps {
|
|
|
1711
1736
|
/**
|
|
1712
1737
|
* The subtitle of the modal.
|
|
1713
1738
|
*/
|
|
1714
|
-
|
|
1739
|
+
subtitle?: string;
|
|
1715
1740
|
/**
|
|
1716
1741
|
* The text content of the modal.
|
|
1717
1742
|
*/
|
|
@@ -2103,28 +2128,61 @@ export type TapToEditProps =
|
|
|
2103
2128
|
export interface BaseTapToEditProps extends Omit<FieldProps, "onChange" | "value"> {
|
|
2104
2129
|
title: string;
|
|
2105
2130
|
value: any;
|
|
2106
|
-
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* Not required if not editable.
|
|
2134
|
+
*/
|
|
2107
2135
|
setValue?: (value: any) => void;
|
|
2108
|
-
|
|
2136
|
+
|
|
2137
|
+
/**
|
|
2138
|
+
* Not required if not editable.
|
|
2139
|
+
*/
|
|
2109
2140
|
onSave?: (value: any) => void | Promise<void>;
|
|
2110
|
-
|
|
2141
|
+
|
|
2142
|
+
/**
|
|
2143
|
+
* If false, the field will not be editable and will be disabled
|
|
2144
|
+
* @default true
|
|
2145
|
+
*/
|
|
2111
2146
|
editable?: boolean;
|
|
2112
|
-
|
|
2147
|
+
|
|
2148
|
+
/**
|
|
2149
|
+
* Enable edit mode from outside the component.
|
|
2150
|
+
*/
|
|
2113
2151
|
isEditing?: boolean;
|
|
2114
|
-
// For changing how the non-editing row renders
|
|
2115
|
-
rowBoxProps?: Partial<BoxProps>;
|
|
2116
2152
|
transform?: (value: any) => string;
|
|
2117
|
-
|
|
2153
|
+
/**
|
|
2154
|
+
* Show a confirmation modal before saving the value.
|
|
2155
|
+
* @default false
|
|
2156
|
+
*/
|
|
2118
2157
|
withConfirmation?: boolean;
|
|
2158
|
+
|
|
2159
|
+
/**
|
|
2160
|
+
* The text content of the confirmation modal.
|
|
2161
|
+
* @default "Are you sure you want save your changes?"
|
|
2162
|
+
*/
|
|
2119
2163
|
confirmationText?: string;
|
|
2120
|
-
|
|
2121
|
-
|
|
2164
|
+
|
|
2165
|
+
/**
|
|
2166
|
+
* The title of the confirmation modal.
|
|
2167
|
+
* @default "Confirm"
|
|
2168
|
+
*/
|
|
2169
|
+
confirmationTitle?: string;
|
|
2170
|
+
|
|
2171
|
+
/**
|
|
2172
|
+
* Field helperText, a description of the field surfaced in the UI
|
|
2173
|
+
* @default "Confirm"
|
|
2174
|
+
*/
|
|
2175
|
+
helperText?: string;
|
|
2176
|
+
|
|
2177
|
+
/**
|
|
2178
|
+
* Only display the helperText in the UI while editing. if false, the helperText is always shown below the value.
|
|
2179
|
+
* @default true
|
|
2180
|
+
*/
|
|
2181
|
+
onlyShowHelperTextWhileEditing?: boolean;
|
|
2182
|
+
|
|
2122
2183
|
// openApi to supported in future
|
|
2123
2184
|
// openApiModel?: string;
|
|
2124
2185
|
// openApiField?: string;
|
|
2125
|
-
showDescriptionAsTooltip?: boolean;
|
|
2126
|
-
// Default true. If false, description is shown below the value always.
|
|
2127
|
-
onlyShowDescriptionWhileEditing?: boolean;
|
|
2128
2186
|
}
|
|
2129
2187
|
|
|
2130
2188
|
export interface APIError {
|
|
@@ -2343,6 +2401,12 @@ export interface SelectFieldPropsBase {
|
|
|
2343
2401
|
*/
|
|
2344
2402
|
helperText?: string;
|
|
2345
2403
|
|
|
2404
|
+
/**
|
|
2405
|
+
* The function to call when the selected value changes.
|
|
2406
|
+
* If requireValue is false and value is undefined, onChange will return empty string.
|
|
2407
|
+
*/
|
|
2408
|
+
onChange: (value: string) => void;
|
|
2409
|
+
|
|
2346
2410
|
/**
|
|
2347
2411
|
* The options available for selection in the select field.
|
|
2348
2412
|
* Each option should have a label and a value.
|
|
@@ -2371,11 +2435,6 @@ export interface SelectFieldPropsWithoutRequire extends SelectFieldPropsBase {
|
|
|
2371
2435
|
* The current value of the select field.
|
|
2372
2436
|
*/
|
|
2373
2437
|
value?: string;
|
|
2374
|
-
|
|
2375
|
-
/**
|
|
2376
|
-
* The function to call when the selected value changes.
|
|
2377
|
-
*/
|
|
2378
|
-
onChange: (value: string | undefined) => void;
|
|
2379
2438
|
}
|
|
2380
2439
|
|
|
2381
2440
|
export interface SelectFieldPropsWithRequire extends SelectFieldPropsBase {
|
|
@@ -340,7 +340,7 @@ const DateCalendar = ({
|
|
|
340
340
|
|
|
341
341
|
// Check if the date is T00:00:00.000Z (it should be), otherwise treat it as a date in the
|
|
342
342
|
// current timezone.
|
|
343
|
-
const dt = DateTime.fromISO(date)
|
|
343
|
+
const dt = DateTime.fromISO(date);
|
|
344
344
|
let dateString: string;
|
|
345
345
|
if (dt.hour === 0 && dt.minute === 0 && dt.second === 0) {
|
|
346
346
|
dateString = dt.toISO()!;
|
package/src/DateTimeField.tsx
CHANGED
|
@@ -26,7 +26,7 @@ export const DateTimeField = ({
|
|
|
26
26
|
return printDateAndTime(val, {timezone, showTimezone: true});
|
|
27
27
|
case "date":
|
|
28
28
|
default:
|
|
29
|
-
return printDate(val, {
|
|
29
|
+
return printDate(val, {ignoreTime: true});
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
[timezone, type]
|
|
@@ -108,9 +108,9 @@ export const DateTimeField = ({
|
|
|
108
108
|
const month = cleanedInput.slice(0, 2);
|
|
109
109
|
const day = cleanedInput.slice(2, 4);
|
|
110
110
|
const year = cleanedInput.slice(4, 8);
|
|
111
|
-
parsedDate = DateTime.fromFormat(`${month}${day}${year}`, "MMddyyyy", {
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
parsedDate = DateTime.fromFormat(`${month}${day}${year}`, "MMddyyyy", {zone: timezone})
|
|
112
|
+
.startOf("day")
|
|
113
|
+
.toUTC(0, {keepLocalTime: true});
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
if (parsedDate?.isValid) {
|
package/src/Field.tsx
CHANGED
|
@@ -48,7 +48,12 @@ export const Field: FC<FieldProps> = ({type, ...rest}) => {
|
|
|
48
48
|
} else if (type === "boolean") {
|
|
49
49
|
return <BooleanField {...(rest as BooleanFieldProps)} />;
|
|
50
50
|
} else if (type && ["date", "time", "datetime"].includes(type)) {
|
|
51
|
-
return
|
|
51
|
+
return (
|
|
52
|
+
<DateTimeField
|
|
53
|
+
{...(rest as DateTimeFieldProps)}
|
|
54
|
+
type={type as "date" | "time" | "datetime"}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
52
57
|
} else if (type === "address") {
|
|
53
58
|
return <AddressField {...(rest as AddressFieldProps)} />;
|
|
54
59
|
} else if (type === "customSelect") {
|
package/src/IconButton.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import {isNative} from "./Utilities";
|
|
|
15
15
|
type ConfirmationModalProps = {
|
|
16
16
|
visible: boolean;
|
|
17
17
|
title: string;
|
|
18
|
-
|
|
18
|
+
subtitle?: string;
|
|
19
19
|
text: string;
|
|
20
20
|
onConfirm: () => void;
|
|
21
21
|
onCancel: () => void;
|
|
@@ -24,7 +24,7 @@ type ConfirmationModalProps = {
|
|
|
24
24
|
const ConfirmationModal: FC<ConfirmationModalProps> = ({
|
|
25
25
|
visible,
|
|
26
26
|
title,
|
|
27
|
-
|
|
27
|
+
subtitle,
|
|
28
28
|
text,
|
|
29
29
|
onConfirm,
|
|
30
30
|
onCancel,
|
|
@@ -35,7 +35,7 @@ const ConfirmationModal: FC<ConfirmationModalProps> = ({
|
|
|
35
35
|
primaryButtonText="Confirm"
|
|
36
36
|
secondaryButtonOnClick={onCancel}
|
|
37
37
|
secondaryButtonText="Cancel"
|
|
38
|
-
|
|
38
|
+
subtitle={subtitle}
|
|
39
39
|
title={title}
|
|
40
40
|
visible={visible}
|
|
41
41
|
onDismiss={onCancel}
|
|
@@ -173,7 +173,7 @@ const IconButtonComponent: FC<IconButtonProps> = ({
|
|
|
173
173
|
)}
|
|
174
174
|
{withConfirmation && (
|
|
175
175
|
<ConfirmationModal
|
|
176
|
-
|
|
176
|
+
subtitle={undefined}
|
|
177
177
|
text={confirmationText}
|
|
178
178
|
title={confirmationHeading}
|
|
179
179
|
visible={showConfirmation}
|
package/src/Modal.tsx
CHANGED
|
@@ -32,7 +32,7 @@ const getModalSize = (size: "sm" | "md" | "lg"): DimensionValue => {
|
|
|
32
32
|
const ModalContent: FC<{
|
|
33
33
|
children?: ModalProps["children"];
|
|
34
34
|
title?: ModalProps["title"];
|
|
35
|
-
|
|
35
|
+
subtitle?: ModalProps["subtitle"];
|
|
36
36
|
text?: ModalProps["text"];
|
|
37
37
|
primaryButtonText?: ModalProps["primaryButtonText"];
|
|
38
38
|
primaryButtonDisabled?: ModalProps["primaryButtonDisabled"];
|
|
@@ -46,7 +46,7 @@ const ModalContent: FC<{
|
|
|
46
46
|
}> = ({
|
|
47
47
|
children,
|
|
48
48
|
title,
|
|
49
|
-
|
|
49
|
+
subtitle,
|
|
50
50
|
text,
|
|
51
51
|
primaryButtonText,
|
|
52
52
|
primaryButtonDisabled,
|
|
@@ -113,14 +113,14 @@ const ModalContent: FC<{
|
|
|
113
113
|
<Heading size="lg">{title}</Heading>
|
|
114
114
|
</View>
|
|
115
115
|
)}
|
|
116
|
-
{
|
|
116
|
+
{subtitle && (
|
|
117
117
|
<View
|
|
118
118
|
accessibilityHint="Modal Sub Heading Text"
|
|
119
|
-
accessibilityLabel={
|
|
119
|
+
accessibilityLabel={subtitle}
|
|
120
120
|
accessibilityRole="text"
|
|
121
|
-
style={{alignSelf: "flex-start", marginTop:
|
|
121
|
+
style={{alignSelf: "flex-start", marginTop: subtitle ? 8 : 0}}
|
|
122
122
|
>
|
|
123
|
-
<Text size="lg">{
|
|
123
|
+
<Text size="lg">{subtitle}</Text>
|
|
124
124
|
</View>
|
|
125
125
|
)}
|
|
126
126
|
{text && (
|
|
@@ -172,7 +172,7 @@ export const Modal: FC<ModalProps> = ({
|
|
|
172
172
|
primaryButtonText,
|
|
173
173
|
secondaryButtonText,
|
|
174
174
|
size = "sm",
|
|
175
|
-
|
|
175
|
+
subtitle,
|
|
176
176
|
text,
|
|
177
177
|
title,
|
|
178
178
|
visible,
|
|
@@ -201,7 +201,7 @@ export const Modal: FC<ModalProps> = ({
|
|
|
201
201
|
|
|
202
202
|
const modalContentProps = {
|
|
203
203
|
title,
|
|
204
|
-
|
|
204
|
+
subtitle,
|
|
205
205
|
text,
|
|
206
206
|
primaryButtonText,
|
|
207
207
|
primaryButtonDisabled,
|
package/src/Page.tsx
CHANGED
|
@@ -61,7 +61,7 @@ export class Page extends React.Component<PageProps, {}> {
|
|
|
61
61
|
<Box
|
|
62
62
|
alignSelf="center"
|
|
63
63
|
avoidKeyboard
|
|
64
|
-
color={this.props.color || "
|
|
64
|
+
color={this.props.color || "base"}
|
|
65
65
|
direction={this.props.direction || "column"}
|
|
66
66
|
display={this.props.display || "flex"}
|
|
67
67
|
flex="grow"
|
package/src/SegmentedControl.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import {Pressable, View} from "react-native";
|
|
3
3
|
|
|
4
4
|
import {SegmentedControlProps} from "./Common";
|
|
5
|
-
import {
|
|
5
|
+
import {Heading} from "./Heading";
|
|
6
6
|
import {useTheme} from "./Theme";
|
|
7
7
|
|
|
8
8
|
export const SegmentedControl = ({
|
|
@@ -23,6 +23,7 @@ export const SegmentedControl = ({
|
|
|
23
23
|
alignItems: "center",
|
|
24
24
|
gap: 4,
|
|
25
25
|
height,
|
|
26
|
+
maxHeight: height,
|
|
26
27
|
borderRadius: theme.primitives.radius3xl,
|
|
27
28
|
borderColor: theme.primitives.neutral300,
|
|
28
29
|
borderWidth: 3,
|
|
@@ -52,7 +53,7 @@ export const SegmentedControl = ({
|
|
|
52
53
|
}}
|
|
53
54
|
onPress={() => onChange(index)}
|
|
54
55
|
>
|
|
55
|
-
<
|
|
56
|
+
<Heading size="sm">{item}</Heading>
|
|
56
57
|
</Pressable>
|
|
57
58
|
))}
|
|
58
59
|
</View>
|
package/src/SelectField.tsx
CHANGED
|
@@ -28,8 +28,8 @@ export const SelectField: FC<SelectFieldProps> = ({
|
|
|
28
28
|
placeholder={!requireValue ? clearOption : {}}
|
|
29
29
|
value={value ?? ""}
|
|
30
30
|
onValueChange={(v) => {
|
|
31
|
-
if (v === ""
|
|
32
|
-
|
|
31
|
+
if (v === undefined || v === "") {
|
|
32
|
+
onChange("");
|
|
33
33
|
} else {
|
|
34
34
|
onChange(v);
|
|
35
35
|
}
|
package/src/TapToEdit.tsx
CHANGED
|
@@ -1,45 +1,33 @@
|
|
|
1
1
|
import React, {ReactElement, useEffect, useState} from "react";
|
|
2
|
-
import {Linking} from "react-native";
|
|
2
|
+
import {Linking, View} from "react-native";
|
|
3
3
|
|
|
4
4
|
import {Box} from "./Box";
|
|
5
5
|
import {Button} from "./Button";
|
|
6
|
-
import {AddressInterface,
|
|
6
|
+
import {AddressInterface, FieldProps, TapToEditProps} from "./Common";
|
|
7
7
|
import {Field} from "./Field";
|
|
8
8
|
import {Icon} from "./Icon";
|
|
9
9
|
// import {useOpenAPISpec} from "./OpenAPIContext";
|
|
10
10
|
import {Text} from "./Text";
|
|
11
|
-
import {Tooltip} from "./Tooltip";
|
|
12
11
|
|
|
13
12
|
const TapToEditTitle = ({
|
|
14
13
|
title,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
onlyShowDescriptionWhileEditing,
|
|
14
|
+
helperText,
|
|
15
|
+
onlyShowHelperTextWhileEditing,
|
|
18
16
|
}: {
|
|
19
|
-
|
|
20
|
-
showDescriptionAsTooltip?: boolean;
|
|
17
|
+
onlyShowHelperTextWhileEditing?: boolean;
|
|
21
18
|
title: string;
|
|
22
|
-
|
|
19
|
+
helperText?: string;
|
|
23
20
|
}): ReactElement => {
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
<Text bold>{title}
|
|
27
|
-
{Boolean(
|
|
21
|
+
return (
|
|
22
|
+
<View style={{flex: 1, justifyContent: "center"}}>
|
|
23
|
+
<Text bold>{title}</Text>
|
|
24
|
+
{Boolean(helperText && !onlyShowHelperTextWhileEditing) && (
|
|
28
25
|
<Text color="secondaryLight" size="sm">
|
|
29
|
-
{
|
|
26
|
+
{helperText}
|
|
30
27
|
</Text>
|
|
31
28
|
)}
|
|
32
|
-
</
|
|
29
|
+
</View>
|
|
33
30
|
);
|
|
34
|
-
if (showDescriptionAsTooltip) {
|
|
35
|
-
return (
|
|
36
|
-
<Tooltip idealPosition="top" text={description}>
|
|
37
|
-
{Title}
|
|
38
|
-
</Tooltip>
|
|
39
|
-
);
|
|
40
|
-
} else {
|
|
41
|
-
return Title;
|
|
42
|
-
}
|
|
43
31
|
};
|
|
44
32
|
|
|
45
33
|
export function formatAddress(address: AddressInterface, asString = false): string {
|
|
@@ -87,20 +75,17 @@ export const TapToEdit = ({
|
|
|
87
75
|
onSave,
|
|
88
76
|
editable = true,
|
|
89
77
|
isEditing = false,
|
|
90
|
-
rowBoxProps,
|
|
91
78
|
transform,
|
|
92
|
-
fieldComponent,
|
|
93
79
|
withConfirmation = false,
|
|
94
80
|
confirmationText = "Are you sure you want to save your changes?",
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
onlyShowDescriptionWhileEditing = true,
|
|
81
|
+
confirmationTitle = "Confirm",
|
|
82
|
+
helperText: propsHelperText,
|
|
83
|
+
onlyShowHelperTextWhileEditing = true,
|
|
99
84
|
...fieldProps
|
|
100
85
|
}: TapToEditProps): ReactElement => {
|
|
101
86
|
const [editing, setEditing] = useState(false);
|
|
102
87
|
const [initialValue, setInitialValue] = useState();
|
|
103
|
-
const
|
|
88
|
+
const helperText: string | undefined = propsHelperText;
|
|
104
89
|
// setInitialValue is called after initial render to handle the case where the value is updated
|
|
105
90
|
useEffect(() => {
|
|
106
91
|
setInitialValue(value);
|
|
@@ -114,37 +99,22 @@ export const TapToEdit = ({
|
|
|
114
99
|
|
|
115
100
|
if (editable && (editing || isEditing)) {
|
|
116
101
|
return (
|
|
117
|
-
<
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
102
|
+
<View style={{flexDirection: "column", width: "100%"}}>
|
|
103
|
+
<View style={{flex: 1, justifyContent: "center"}}>
|
|
104
|
+
<Text bold>{title}</Text>
|
|
105
|
+
</View>
|
|
106
|
+
<View style={{gap: 16}}>
|
|
121
107
|
<Field
|
|
122
|
-
|
|
123
|
-
|
|
108
|
+
grow={fieldProps?.type === "textarea" ? fieldProps.grow ?? true : undefined}
|
|
109
|
+
helperText={helperText}
|
|
110
|
+
row={fieldProps?.type === "textarea" ? 5 : undefined}
|
|
124
111
|
type={(fieldProps?.type ?? "text") as NonNullable<FieldProps["type"]>}
|
|
125
112
|
value={value}
|
|
126
113
|
onChange={setValue ?? (() => {})}
|
|
127
114
|
{...(fieldProps as any)}
|
|
128
115
|
/>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<Box direction="row">
|
|
132
|
-
<Button
|
|
133
|
-
confirmationText={confirmationText}
|
|
134
|
-
modalTitle={confirmationHeading}
|
|
135
|
-
text="Save"
|
|
136
|
-
withConfirmation={withConfirmation}
|
|
137
|
-
onClick={async (): Promise<void> => {
|
|
138
|
-
if (!onSave) {
|
|
139
|
-
console.error("No onSave provided for editable TapToEdit");
|
|
140
|
-
} else {
|
|
141
|
-
setInitialValue(value);
|
|
142
|
-
await onSave(value);
|
|
143
|
-
}
|
|
144
|
-
setEditing(false);
|
|
145
|
-
}}
|
|
146
|
-
/>
|
|
147
|
-
<Box marginLeft={2}>
|
|
116
|
+
{editing && !isEditing && (
|
|
117
|
+
<View style={{flexDirection: "row", justifyContent: "flex-end", gap: 16}}>
|
|
148
118
|
<Button
|
|
149
119
|
text="Cancel"
|
|
150
120
|
variant="muted"
|
|
@@ -155,10 +125,27 @@ export const TapToEdit = ({
|
|
|
155
125
|
setEditing(false);
|
|
156
126
|
}}
|
|
157
127
|
/>
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
128
|
+
<View style={{marginLeft: 8}}>
|
|
129
|
+
<Button
|
|
130
|
+
confirmationText={confirmationText}
|
|
131
|
+
modalTitle={confirmationTitle}
|
|
132
|
+
text="Save"
|
|
133
|
+
withConfirmation={withConfirmation}
|
|
134
|
+
onClick={async (): Promise<void> => {
|
|
135
|
+
if (!onSave) {
|
|
136
|
+
console.error("No onSave provided for editable TapToEdit");
|
|
137
|
+
} else {
|
|
138
|
+
setInitialValue(value);
|
|
139
|
+
await onSave(value);
|
|
140
|
+
}
|
|
141
|
+
setEditing(false);
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
</View>
|
|
145
|
+
</View>
|
|
146
|
+
)}
|
|
147
|
+
</View>
|
|
148
|
+
</View>
|
|
162
149
|
);
|
|
163
150
|
} else {
|
|
164
151
|
let displayValue = value;
|
|
@@ -169,6 +156,7 @@ export const TapToEdit = ({
|
|
|
169
156
|
// If no transform, try and display the value reasonably.
|
|
170
157
|
if (fieldProps?.type === "boolean") {
|
|
171
158
|
displayValue = value ? "Yes" : "No";
|
|
159
|
+
// TODO: put transform back in after field types are updated
|
|
172
160
|
// } else if (fieldProps?.type === "percent") {
|
|
173
161
|
// // Prevent floating point errors from showing up by using parseFloat and precision.
|
|
174
162
|
// // Pass through parseFloat again to trim off insignificant zeroes.
|
|
@@ -217,23 +205,27 @@ export const TapToEdit = ({
|
|
|
217
205
|
// For textarea to display correctly, we place the title on its own line, then the text
|
|
218
206
|
// on the next line. This is because the textarea will take up the full width of the row.
|
|
219
207
|
return (
|
|
220
|
-
<
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
{...(rowBoxProps as Exclude<BoxProps, "onClick">)}
|
|
208
|
+
<View
|
|
209
|
+
style={{
|
|
210
|
+
alignItems: fieldProps?.type === "textarea" ? "flex-start" : "center",
|
|
211
|
+
flexDirection: fieldProps?.type === "textarea" ? "column" : "row",
|
|
212
|
+
justifyContent: "space-between",
|
|
213
|
+
width: "100%",
|
|
214
|
+
}}
|
|
228
215
|
>
|
|
229
|
-
<
|
|
216
|
+
<View style={{flexDirection: "row", width: "100%", gap: 16}}>
|
|
230
217
|
<TapToEditTitle
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
showDescriptionAsTooltip={showDescriptionAsTooltip}
|
|
218
|
+
helperText={helperText}
|
|
219
|
+
onlyShowHelperTextWhileEditing={onlyShowHelperTextWhileEditing}
|
|
234
220
|
title={title}
|
|
235
221
|
/>
|
|
236
|
-
<
|
|
222
|
+
<View
|
|
223
|
+
style={{
|
|
224
|
+
flexDirection: "row",
|
|
225
|
+
flex: 1,
|
|
226
|
+
justifyContent: "flex-end",
|
|
227
|
+
}}
|
|
228
|
+
>
|
|
237
229
|
<Box
|
|
238
230
|
accessibilityHint=""
|
|
239
231
|
accessibilityLabel="Link"
|
|
@@ -257,30 +249,16 @@ export const TapToEdit = ({
|
|
|
257
249
|
<Icon iconName="pencil" size="md" />
|
|
258
250
|
</Box>
|
|
259
251
|
)}
|
|
260
|
-
</
|
|
261
|
-
</
|
|
252
|
+
</View>
|
|
253
|
+
</View>
|
|
262
254
|
{fieldProps?.type === "textarea" && (
|
|
263
|
-
|
|
264
|
-
<
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
</Box>
|
|
269
|
-
{editable && (
|
|
270
|
-
<Box
|
|
271
|
-
accessibilityHint=""
|
|
272
|
-
accessibilityLabel="Edit"
|
|
273
|
-
alignSelf="end"
|
|
274
|
-
marginLeft={2}
|
|
275
|
-
width={16}
|
|
276
|
-
onClick={(): void => setEditing(true)}
|
|
277
|
-
>
|
|
278
|
-
<Icon color="primary" iconName="pencil" size="md" />
|
|
279
|
-
</Box>
|
|
280
|
-
)}
|
|
281
|
-
</>
|
|
255
|
+
<View style={{marginTop: 8, paddingVertical: 8, width: "100%"}}>
|
|
256
|
+
<Text align="left" underline={isClickable}>
|
|
257
|
+
{displayValue}
|
|
258
|
+
</Text>
|
|
259
|
+
</View>
|
|
282
260
|
)}
|
|
283
|
-
</
|
|
261
|
+
</View>
|
|
284
262
|
);
|
|
285
263
|
}
|
|
286
264
|
};
|