@draftbit/core 43.4.10 → 43.4.11-776ef8.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/lib/commonjs/components/FAB.js +19 -5
- package/lib/commonjs/components/FAB.js.map +1 -1
- package/lib/commonjs/components/FieldSearchBarFull.js.map +1 -1
- package/lib/commonjs/components/Justification.js +3 -0
- package/lib/commonjs/components/ResizeMode.js +3 -0
- package/lib/commonjs/mappings/Icon.js +3 -1
- package/lib/commonjs/mappings/Icon.js.map +1 -1
- package/lib/commonjs/mappings/RowHeadlineImageCaption.js.map +1 -1
- package/lib/commonjs/mappings/RowHeadlineImageIcon.js.map +1 -1
- package/lib/module/components/Justification.js +1 -1
- package/lib/module/components/ResizeMode.js +1 -1
- package/lib/module/mappings/Icon.js +3 -1
- package/lib/module/mappings/Icon.js.map +1 -1
- package/lib/typescript/src/mappings/Icon.d.ts +1 -1
- package/package.json +2 -2
- package/src/Provider.js +9 -0
- package/src/components/Accordion/AccordionGroup.js +44 -0
- package/src/components/Accordion/AccordionItem.js +32 -0
- package/src/components/Accordion/index.js +2 -0
- package/src/components/ActionSheet/ActionSheet.js +45 -0
- package/src/components/ActionSheet/ActionSheetCancel.js +6 -0
- package/src/components/ActionSheet/ActionSheetItem.js +30 -0
- package/src/components/ActionSheet/index.js +3 -0
- package/src/components/AnimatedCircularProgress.js +43 -0
- package/src/components/AspectRatio.js +18 -0
- package/src/components/AvatarEdit.js +30 -0
- package/src/components/Button.js +112 -0
- package/src/components/Card.js +57 -0
- package/src/components/CardBlock.js +54 -0
- package/src/components/CardContainer.js +69 -0
- package/src/components/CardContainerRating.js +79 -0
- package/src/components/CardContainerShortImage.js +33 -0
- package/src/components/CardInline.js +36 -0
- package/src/components/Carousel.js +66 -0
- package/src/components/Checkbox/Checkbox.js +63 -0
- package/src/components/Checkbox/CheckboxGroup.js +21 -0
- package/src/components/Checkbox/CheckboxRow.js +77 -0
- package/src/components/Checkbox/context.js +14 -0
- package/src/components/Checkbox/index.js +3 -0
- package/src/components/CircleImage.js +8 -0
- package/src/components/CircularProgress.js +78 -0
- package/src/components/Config.js +63 -0
- package/src/components/Container.js +44 -0
- package/src/components/DatePicker/DatePicker.js +370 -0
- package/src/components/DatePicker/DatePickerComponent.js +13 -0
- package/src/components/DatePicker/DatePickerComponent.web.js +30 -0
- package/src/components/DatePicker/DatePickerComponentType.js +1 -0
- package/src/components/DeprecatedButton.js +95 -0
- package/src/components/DeprecatedCardWrapper.js +18 -0
- package/src/components/DeprecatedFAB.js +115 -0
- package/src/components/Divider.js +13 -0
- package/src/components/Elevation.js +20 -0
- package/src/components/FAB.js +46 -0
- package/src/components/FieldSearchBarFull.js +53 -0
- package/src/components/FormRow.js +19 -0
- package/src/components/Header.js +44 -0
- package/src/components/HeaderLarge.js +7 -0
- package/src/components/HeaderMedium.js +7 -0
- package/src/components/HeaderOverline.js +7 -0
- package/src/components/IconButton.js +35 -0
- package/src/components/Image.js +47 -0
- package/src/components/Justification.js +1 -0
- package/src/components/Layout.js +50 -0
- package/src/components/NumberInput.js +50 -0
- package/src/components/Picker/Picker.js +56 -0
- package/src/components/Picker/PickerComponent.android.js +68 -0
- package/src/components/Picker/PickerComponent.ios.js +78 -0
- package/src/components/Picker/PickerComponent.web.js +69 -0
- package/src/components/Picker/PickerTypes.js +1 -0
- package/src/components/Portal/Portal.js +35 -0
- package/src/components/Portal/PortalConsumer.js +28 -0
- package/src/components/Portal/PortalHost.js +105 -0
- package/src/components/Portal/PortalManager.js +29 -0
- package/src/components/ProgressBar.js +118 -0
- package/src/components/ProgressCircle.js +13 -0
- package/src/components/ProgressIndicator.js +27 -0
- package/src/components/RadioButton/RadioButton.js +17 -0
- package/src/components/RadioButton/RadioButtonFieldGroup.js +17 -0
- package/src/components/RadioButton/RadioButtonGroup.js +39 -0
- package/src/components/RadioButton/RadioButtonRow.js +76 -0
- package/src/components/RadioButton/context.js +14 -0
- package/src/components/RadioButton/index.js +4 -0
- package/src/components/ResizeMode.js +1 -0
- package/src/components/Row.js +48 -0
- package/src/components/RowBodyIcon.js +8 -0
- package/src/components/RowHeadlineImageCaption.js +12 -0
- package/src/components/RowHeadlineImageIcon.js +14 -0
- package/src/components/ScreenContainer.js +35 -0
- package/src/components/Slider.js +63 -0
- package/src/components/StarRating.js +50 -0
- package/src/components/StepIndicator.js +346 -0
- package/src/components/Stepper.js +53 -0
- package/src/components/Surface.js +23 -0
- package/src/components/Swiper/Swiper.js +18 -0
- package/src/components/Swiper/SwiperItem.js +9 -0
- package/src/components/Swiper/index.js +2 -0
- package/src/components/Switch.js +56 -0
- package/src/components/Text.js +28 -0
- package/src/components/TextField.js +419 -0
- package/src/components/ToggleButton.js +39 -0
- package/src/components/Touchable.js +12 -0
- package/src/components/Touchable.web.js +2 -0
- package/src/components/Typography.js +36 -0
- package/src/components/useAuthState.js +31 -0
- package/src/constants.js +10 -0
- package/src/hooks.js +12 -0
- package/src/index.js +50 -0
- package/src/interfaces/Icon.js +8 -0
- package/src/mappings/Accordion.js +37 -0
- package/src/mappings/AccordionItem.js +16 -0
- package/src/mappings/ActionSheet.js +13 -0
- package/src/mappings/ActionSheetCancel.js +19 -0
- package/src/mappings/ActionSheetItem.js +22 -0
- package/src/mappings/ActivityIndicator.js +53 -0
- package/src/mappings/AudioPlayer.js +20 -0
- package/src/mappings/AvatarEdit.js +37 -0
- package/src/mappings/BlurView.js +41 -0
- package/src/mappings/Button.js +56 -0
- package/src/mappings/Card.js +52 -0
- package/src/mappings/CardBlock.js +122 -0
- package/src/mappings/CardContainer.js +102 -0
- package/src/mappings/CardContainerRating.js +124 -0
- package/src/mappings/CardContainerShortImage.js +118 -0
- package/src/mappings/CardInline.js +51 -0
- package/src/mappings/Carousel.js +18 -0
- package/src/mappings/Checkbox.js +45 -0
- package/src/mappings/CheckboxGroup.js +25 -0
- package/src/mappings/CheckboxRow.js +37 -0
- package/src/mappings/CircleImage.js +24 -0
- package/src/mappings/Container.js +29 -0
- package/src/mappings/CustomCode.js +8 -0
- package/src/mappings/DatePicker.js +146 -0
- package/src/mappings/Divider.js +26 -0
- package/src/mappings/FAB.js +36 -0
- package/src/mappings/Fetch.js +12 -0
- package/src/mappings/FieldSearchBarFull.js +49 -0
- package/src/mappings/FlatList.js +19 -0
- package/src/mappings/HeaderLarge.js +28 -0
- package/src/mappings/HeaderMedium.js +54 -0
- package/src/mappings/HeaderOverline.js +54 -0
- package/src/mappings/Icon.js +25 -0
- package/src/mappings/Icon.ts +4 -1
- package/src/mappings/IconButton.js +30 -0
- package/src/mappings/Image.js +15 -0
- package/src/mappings/ImageBackground.js +28 -0
- package/src/mappings/KeyboardAvoidingView.js +40 -0
- package/src/mappings/Layout.js +195 -0
- package/src/mappings/LinearGradient.js +77 -0
- package/src/mappings/MapCallout.js +19 -0
- package/src/mappings/MapMarker.js +46 -0
- package/src/mappings/Modal.js +41 -0
- package/src/mappings/Picker.js +137 -0
- package/src/mappings/ProgressBar.js +100 -0
- package/src/mappings/ProgressCircle.js +108 -0
- package/src/mappings/ProgressIndicator.js +180 -0
- package/src/mappings/RadioButton.js +50 -0
- package/src/mappings/RadioButtonGroup.js +16 -0
- package/src/mappings/RadioButtonRow.js +37 -0
- package/src/mappings/RowBodyIcon.js +75 -0
- package/src/mappings/RowHeadlineImageCaption.js +167 -0
- package/src/mappings/RowHeadlineImageIcon.js +99 -0
- package/src/mappings/SafeAreaView.js +33 -0
- package/src/mappings/ScrollView.js +30 -0
- package/src/mappings/Slider.js +59 -0
- package/src/mappings/StarRating.js +46 -0
- package/src/mappings/Stepper.js +28 -0
- package/src/mappings/Surface.js +13 -0
- package/src/mappings/Swiper.js +60 -0
- package/src/mappings/SwiperItem.js +8 -0
- package/src/mappings/Switch.js +75 -0
- package/src/mappings/Text.js +227 -0
- package/src/mappings/TextArea.js +52 -0
- package/src/mappings/TextField.js +158 -0
- package/src/mappings/TextInput.js +208 -0
- package/src/mappings/ToggleButton.js +50 -0
- package/src/mappings/Touchable.js +12 -0
- package/src/mappings/Video.js +74 -0
- package/src/mappings/View.js +206 -0
- package/src/mappings/WebView.js +13 -0
- package/src/styles/DarkTheme.js +26 -0
- package/src/styles/DefaultTheme.js +111 -0
- package/src/styles/fonts.js +62 -0
- package/src/styles/overlay.js +60 -0
- package/src/styles/shadow.js +51 -0
- package/src/theming.js +3 -0
- package/src/utilities.js +54 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { TextInput } from "react-native";
|
|
3
|
+
import { isString, isNumber, isNaN } from "lodash";
|
|
4
|
+
const NumberInput = ({ onChangeText, value, defaultValue, ...props }) => {
|
|
5
|
+
const formatValueToStringNumber = (valueToFormat, currentStringNumberValue) => {
|
|
6
|
+
if (valueToFormat != null) {
|
|
7
|
+
if (isString(valueToFormat) && valueToFormat !== "") {
|
|
8
|
+
if (/^0[1-9]$/.test(valueToFormat)) {
|
|
9
|
+
return valueToFormat.slice(1);
|
|
10
|
+
}
|
|
11
|
+
else if (/^[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)$/.test(valueToFormat)) {
|
|
12
|
+
return valueToFormat;
|
|
13
|
+
}
|
|
14
|
+
else if (currentStringNumberValue) {
|
|
15
|
+
return currentStringNumberValue;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
else if (isNumber(valueToFormat) && !isNaN(valueToFormat)) {
|
|
19
|
+
return valueToFormat.toString();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return "0";
|
|
23
|
+
};
|
|
24
|
+
const [currentStringNumberValue, setCurrentStringNumberValue] = useState(formatValueToStringNumber("0"));
|
|
25
|
+
const handleChangeText = (newValue) => {
|
|
26
|
+
const newStringNumberValue = formatValueToStringNumber(newValue, currentStringNumberValue);
|
|
27
|
+
const number = parseFloat(newStringNumberValue);
|
|
28
|
+
setCurrentStringNumberValue(newStringNumberValue);
|
|
29
|
+
onChangeText?.(number);
|
|
30
|
+
};
|
|
31
|
+
/* set currentStringNumberValue directly to defaultValue if it exists on load
|
|
32
|
+
( no need to use TextInput's defaultValue because its value is always controlled & set ) */
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const defaultStringNumberValue = formatValueToStringNumber(defaultValue, currentStringNumberValue);
|
|
35
|
+
if (currentStringNumberValue !== defaultStringNumberValue) {
|
|
36
|
+
setCurrentStringNumberValue(defaultStringNumberValue);
|
|
37
|
+
}
|
|
38
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
39
|
+
}, []);
|
|
40
|
+
// set new (or original) value if different from current (or initialized "0") value
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const nextStringNumberValue = formatValueToStringNumber(value, currentStringNumberValue);
|
|
43
|
+
if (currentStringNumberValue !== nextStringNumberValue) {
|
|
44
|
+
handleChangeText(nextStringNumberValue);
|
|
45
|
+
}
|
|
46
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
47
|
+
}, [value]);
|
|
48
|
+
return (React.createElement(TextInput, { keyboardType: "numeric", value: currentStringNumberValue, onChangeText: handleChangeText, ...props }));
|
|
49
|
+
};
|
|
50
|
+
export default NumberInput;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { withTheme } from "../../theming";
|
|
3
|
+
//@ts-ignore
|
|
4
|
+
import PickerComponent from "./PickerComponent"; //unable to find file due to using .android/.web/.ios
|
|
5
|
+
function normalizeOptions(options) {
|
|
6
|
+
if (options.length === 0) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
if (typeof options[0] === "string") {
|
|
10
|
+
return options.map((option) => ({
|
|
11
|
+
label: option,
|
|
12
|
+
value: String(option),
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
if (options[0].label && options[0].value) {
|
|
16
|
+
return options.map((option) => {
|
|
17
|
+
return {
|
|
18
|
+
label: option.label,
|
|
19
|
+
value: String(option.value),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
throw new Error('Picker options must be either an array of strings or array of { "label": string; "value": string; } objects.');
|
|
24
|
+
}
|
|
25
|
+
const Picker = ({ options = [], placeholder, onValueChange: onValueChangeOverride, value, defaultValue, ...props }) => {
|
|
26
|
+
const [internalValue, setInternalValue] = React.useState(value || defaultValue);
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
if (value != null) {
|
|
29
|
+
setInternalValue(value);
|
|
30
|
+
}
|
|
31
|
+
}, [value]);
|
|
32
|
+
React.useEffect(() => {
|
|
33
|
+
if (defaultValue != null) {
|
|
34
|
+
setInternalValue(defaultValue);
|
|
35
|
+
}
|
|
36
|
+
}, [defaultValue]);
|
|
37
|
+
const onValueChange = React.useCallback((itemValue, itemIndex) => {
|
|
38
|
+
if (placeholder && itemIndex === 0) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
onValueChangeOverride &&
|
|
42
|
+
onValueChangeOverride(String(itemValue), itemIndex);
|
|
43
|
+
}, [placeholder, onValueChangeOverride]);
|
|
44
|
+
const normalizedOptions = normalizeOptions(options);
|
|
45
|
+
const pickerOptions = placeholder
|
|
46
|
+
? [{ value: placeholder, label: placeholder }, ...normalizedOptions]
|
|
47
|
+
: normalizedOptions;
|
|
48
|
+
const handleValueChange = (newValue, itemIndex) => {
|
|
49
|
+
setInternalValue(newValue);
|
|
50
|
+
if (onValueChange) {
|
|
51
|
+
onValueChange(newValue, itemIndex);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
return (React.createElement(PickerComponent, { ...props, selectedValue: String(internalValue), placeholder: placeholder, options: pickerOptions, onValueChange: handleValueChange }));
|
|
55
|
+
};
|
|
56
|
+
export default withTheme(Picker);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import omit from "lodash.omit";
|
|
4
|
+
import { withTheme } from "../../theming";
|
|
5
|
+
import { Picker as NativePicker } from "@react-native-picker/picker";
|
|
6
|
+
import { extractStyles } from "../../utilities";
|
|
7
|
+
import TextField from "../TextField";
|
|
8
|
+
import Touchable from "../Touchable";
|
|
9
|
+
const Picker = ({ style, options, placeholder, selectedValue, disabled = false, onValueChange: onValueChangeOverride = () => { }, ...props }) => {
|
|
10
|
+
const { viewStyles: { borderRadius, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
11
|
+
borderWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
12
|
+
borderTopWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
13
|
+
borderRightWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
14
|
+
borderBottomWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
15
|
+
borderLeftWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
16
|
+
borderColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
17
|
+
backgroundColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
18
|
+
padding, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
19
|
+
paddingTop, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
20
|
+
paddingRight, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
21
|
+
paddingBottom, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
22
|
+
paddingLeft, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
23
|
+
...viewStyles }, } = extractStyles(style);
|
|
24
|
+
const textField = React.useRef(undefined);
|
|
25
|
+
const onValueChange = (itemValue, itemIndex) => {
|
|
26
|
+
toggleFocus();
|
|
27
|
+
onValueChangeOverride(itemValue, itemIndex);
|
|
28
|
+
};
|
|
29
|
+
const toggleFocus = () => {
|
|
30
|
+
if (!disabled) {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
textField.current.toggleFocus(); // cannot determine if method exists due to component being wrapped in a withTheme()
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const stylesWithoutMargin = style &&
|
|
36
|
+
omit(StyleSheet.flatten(style), [
|
|
37
|
+
"margin",
|
|
38
|
+
"marginTop",
|
|
39
|
+
"marginRight",
|
|
40
|
+
"marginBottom",
|
|
41
|
+
"marginLeft",
|
|
42
|
+
]);
|
|
43
|
+
const selectedLabel = selectedValue &&
|
|
44
|
+
(options.find((o) => o.value === selectedValue)?.label ?? selectedValue);
|
|
45
|
+
return (React.createElement(Touchable, { disabled: disabled, onPress: toggleFocus, style: [styles.container, viewStyles] },
|
|
46
|
+
React.createElement(View, null,
|
|
47
|
+
React.createElement(NativePicker, { enabled: !disabled, selectedValue: selectedValue, onValueChange: onValueChange, style: {
|
|
48
|
+
opacity: 0,
|
|
49
|
+
position: "absolute",
|
|
50
|
+
top: 0,
|
|
51
|
+
left: 0,
|
|
52
|
+
right: 0,
|
|
53
|
+
bottom: 0,
|
|
54
|
+
width: "100%",
|
|
55
|
+
} }, options.map((o) => (React.createElement(NativePicker.Item, { label: o.label, value: o.value, key: o.value })))),
|
|
56
|
+
React.createElement(View, { pointerEvents: "none" },
|
|
57
|
+
React.createElement(TextField, { ...props, value: selectedLabel, placeholder: placeholder,
|
|
58
|
+
// @ts-ignore
|
|
59
|
+
ref: textField, disabled: disabled,
|
|
60
|
+
// @ts-expect-error
|
|
61
|
+
style: stylesWithoutMargin })))));
|
|
62
|
+
};
|
|
63
|
+
const styles = StyleSheet.create({
|
|
64
|
+
container: {
|
|
65
|
+
alignSelf: "stretch",
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
export default withTheme(Picker);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import { SafeAreaView } from "react-native-safe-area-context";
|
|
4
|
+
import omit from "lodash.omit";
|
|
5
|
+
import { Picker as NativePicker } from "@react-native-picker/picker";
|
|
6
|
+
import { withTheme } from "../../theming";
|
|
7
|
+
import Portal from "../Portal/Portal";
|
|
8
|
+
import Button from "../DeprecatedButton";
|
|
9
|
+
import TextField from "../TextField";
|
|
10
|
+
import Touchable from "../Touchable";
|
|
11
|
+
import { extractStyles } from "../../utilities";
|
|
12
|
+
const Picker = ({ Icon, style, options, placeholder, selectedValue, disabled = false, onValueChange = () => { }, theme: { colors }, ...props }) => {
|
|
13
|
+
const { viewStyles: { borderRadius, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
14
|
+
borderWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
15
|
+
borderTopWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
16
|
+
borderRightWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
17
|
+
borderBottomWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
18
|
+
borderLeftWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
19
|
+
borderColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
20
|
+
backgroundColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
21
|
+
padding, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
22
|
+
paddingTop, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
23
|
+
paddingRight, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
24
|
+
paddingBottom, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
25
|
+
paddingLeft, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
26
|
+
...viewStyles }, } = extractStyles(style);
|
|
27
|
+
const textField = React.useRef(undefined);
|
|
28
|
+
const [pickerVisible, setIsPickerVisible] = React.useState(false);
|
|
29
|
+
const toggleVisibility = () => {
|
|
30
|
+
setIsPickerVisible(!pickerVisible);
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
textField.current.toggleFocus(); // cannot determine if method exists due to component being wrapped in a withTheme()
|
|
33
|
+
};
|
|
34
|
+
const stylesWithoutMargin = style &&
|
|
35
|
+
omit(StyleSheet.flatten(style), [
|
|
36
|
+
"margin",
|
|
37
|
+
"marginTop",
|
|
38
|
+
"marginRight",
|
|
39
|
+
"marginBottom",
|
|
40
|
+
"marginLeft",
|
|
41
|
+
]);
|
|
42
|
+
const selectedLabel = selectedValue &&
|
|
43
|
+
(options.find((o) => o.value === selectedValue)?.label ?? selectedValue);
|
|
44
|
+
return (React.createElement(View, { style: [styles.container, viewStyles] },
|
|
45
|
+
React.createElement(Touchable, { disabled: disabled, onPress: toggleVisibility },
|
|
46
|
+
React.createElement(TextField, { ...props, value: String(selectedLabel), placeholder: placeholder,
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
ref: textField, disabled: disabled, pointerEvents: "none",
|
|
49
|
+
// @ts-expect-error
|
|
50
|
+
style: stylesWithoutMargin, Icon: Icon })),
|
|
51
|
+
pickerVisible && (React.createElement(Portal, null,
|
|
52
|
+
React.createElement(View, { style: [styles.picker, { backgroundColor: colors.divider }] },
|
|
53
|
+
React.createElement(SafeAreaView, { style: styles.pickerContainer },
|
|
54
|
+
React.createElement(Button, { Icon: Icon, type: "text", onPress: toggleVisibility, style: styles.closeButton }, "Close"),
|
|
55
|
+
React.createElement(NativePicker, { style: { backgroundColor: "white" }, selectedValue: selectedValue, onValueChange: onValueChange }, options.map((o) => (React.createElement(NativePicker.Item, { label: o.label, value: o.value, key: o.value }))))))))));
|
|
56
|
+
};
|
|
57
|
+
const styles = StyleSheet.create({
|
|
58
|
+
container: {
|
|
59
|
+
alignSelf: "stretch",
|
|
60
|
+
},
|
|
61
|
+
picker: {
|
|
62
|
+
position: "absolute",
|
|
63
|
+
bottom: 0,
|
|
64
|
+
left: 0,
|
|
65
|
+
right: 0,
|
|
66
|
+
flexDirection: "row",
|
|
67
|
+
justifyContent: "center",
|
|
68
|
+
},
|
|
69
|
+
pickerContainer: {
|
|
70
|
+
backgroundColor: "white",
|
|
71
|
+
flexDirection: "column",
|
|
72
|
+
width: "100%",
|
|
73
|
+
},
|
|
74
|
+
closeButton: {
|
|
75
|
+
alignSelf: "flex-end",
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
export default withTheme(Picker);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import { Picker as NativePicker } from "@react-native-picker/picker";
|
|
4
|
+
import omit from "lodash.omit";
|
|
5
|
+
import { withTheme } from "../../theming";
|
|
6
|
+
import { extractStyles } from "../../utilities";
|
|
7
|
+
import TextField from "../TextField";
|
|
8
|
+
import Touchable from "../Touchable";
|
|
9
|
+
const Picker = ({ style, options, placeholder, selectedValue, disabled = false, onValueChange: onValueChangeOverride = () => { }, ...props }) => {
|
|
10
|
+
const { viewStyles: { borderRadius, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
11
|
+
borderWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
12
|
+
borderTopWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
13
|
+
borderRightWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
14
|
+
borderBottomWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
15
|
+
borderLeftWidth, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
16
|
+
borderColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
17
|
+
backgroundColor, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
18
|
+
padding, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
19
|
+
paddingTop, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
20
|
+
paddingRight, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
21
|
+
paddingBottom, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
22
|
+
paddingLeft, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
23
|
+
...viewStyles }, } = extractStyles(style);
|
|
24
|
+
const textField = React.useRef(undefined);
|
|
25
|
+
const onValueChange = (itemValue, itemIndex) => {
|
|
26
|
+
toggleFocus();
|
|
27
|
+
onValueChangeOverride(itemValue, itemIndex);
|
|
28
|
+
};
|
|
29
|
+
const toggleFocus = () => {
|
|
30
|
+
if (!disabled) {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
textField.current.toggleFocus(); // cannot determine if method exists due to component being wrapped in a withTheme()
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const stylesWithoutMargin = style &&
|
|
36
|
+
omit(StyleSheet.flatten(style), [
|
|
37
|
+
"margin",
|
|
38
|
+
"marginTop",
|
|
39
|
+
"marginRight",
|
|
40
|
+
"marginBottom",
|
|
41
|
+
"marginLeft",
|
|
42
|
+
]);
|
|
43
|
+
const selectedLabel = selectedValue &&
|
|
44
|
+
(options.find((o) => o.value === selectedValue)?.label ?? selectedValue);
|
|
45
|
+
return (React.createElement(Touchable, { disabled: disabled, onPress: toggleFocus, style: [styles.container, viewStyles] },
|
|
46
|
+
React.createElement(View, null,
|
|
47
|
+
React.createElement(NativePicker, { enabled: !disabled, selectedValue: selectedValue, onValueChange: onValueChange, style: {
|
|
48
|
+
flex: 1,
|
|
49
|
+
opacity: 0,
|
|
50
|
+
position: "absolute",
|
|
51
|
+
top: 0,
|
|
52
|
+
left: 0,
|
|
53
|
+
right: 0,
|
|
54
|
+
bottom: 0,
|
|
55
|
+
width: "100%",
|
|
56
|
+
} }, options.map((o) => (React.createElement(NativePicker.Item, { label: o.label, value: o.value, key: o.value })))),
|
|
57
|
+
React.createElement(View, { pointerEvents: "none" },
|
|
58
|
+
React.createElement(TextField, { ...props, value: selectedLabel, placeholder: placeholder,
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
ref: textField, disabled: disabled,
|
|
61
|
+
// @ts-expect-error
|
|
62
|
+
style: stylesWithoutMargin })))));
|
|
63
|
+
};
|
|
64
|
+
const styles = StyleSheet.create({
|
|
65
|
+
container: {
|
|
66
|
+
alignSelf: "stretch",
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
export default withTheme(Picker);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import PortalConsumer from "./PortalConsumer";
|
|
3
|
+
import PortalHost, { PortalContext } from "./PortalHost";
|
|
4
|
+
import { ThemeProvider, withTheme } from "../../theming";
|
|
5
|
+
/**
|
|
6
|
+
* Portal allows to render a component at a different place in the parent tree.
|
|
7
|
+
* You can use it to render content which should appear above other elements, similar to `Modal`.
|
|
8
|
+
* It requires a [`Portal.Host`](portal-host.html) component to be rendered somewhere in the parent tree.
|
|
9
|
+
*
|
|
10
|
+
* ## Usage
|
|
11
|
+
* ```js
|
|
12
|
+
* import * as React from 'react';
|
|
13
|
+
* import { Portal, Text } from 'react-native-paper';
|
|
14
|
+
*
|
|
15
|
+
* export default class MyComponent extends React.Component {
|
|
16
|
+
* render() {
|
|
17
|
+
* return (
|
|
18
|
+
* <Portal>
|
|
19
|
+
* <Text>This is rendered at a different place</Text>
|
|
20
|
+
* </Portal>
|
|
21
|
+
* );
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
class Portal extends React.Component {
|
|
27
|
+
// @component ./PortalHost.tsx
|
|
28
|
+
static Host = PortalHost;
|
|
29
|
+
render() {
|
|
30
|
+
const { children, theme } = this.props;
|
|
31
|
+
return (React.createElement(PortalContext.Consumer, null, (manager) => (React.createElement(PortalConsumer, { manager: manager },
|
|
32
|
+
React.createElement(ThemeProvider, { theme: theme }, children)))));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export default withTheme(Portal);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export default class PortalConsumer extends React.Component {
|
|
3
|
+
async componentDidMount() {
|
|
4
|
+
this.checkManager();
|
|
5
|
+
// Delay updating to prevent React from going to infinite loop
|
|
6
|
+
await Promise.resolve();
|
|
7
|
+
this.key = this.props.manager.mount(this.props.children);
|
|
8
|
+
}
|
|
9
|
+
componentDidUpdate() {
|
|
10
|
+
this.checkManager();
|
|
11
|
+
this.props.manager.update(this.key, this.props.children);
|
|
12
|
+
}
|
|
13
|
+
componentWillUnmount() {
|
|
14
|
+
this.checkManager();
|
|
15
|
+
this.props.manager.unmount(this.key);
|
|
16
|
+
}
|
|
17
|
+
key;
|
|
18
|
+
checkManager() {
|
|
19
|
+
if (!this.props.manager) {
|
|
20
|
+
throw new Error("Looks like you forgot to wrap your root component with `Provider` component from `react-native-paper`.\n\n" +
|
|
21
|
+
"Please read our getting-started guide and make sure you've followed all the required steps.\n\n" +
|
|
22
|
+
"https://callstack.github.io/react-native-paper/getting-started.html");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
render() {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
import PortalManager from "./PortalManager";
|
|
4
|
+
export const PortalContext = React.createContext(null);
|
|
5
|
+
/**
|
|
6
|
+
* Portal host renders all of its children `Portal` elements.
|
|
7
|
+
* For example, you can wrap a screen in `Portal.Host` to render items above the screen.
|
|
8
|
+
* If you're using the `Provider` component, it already includes `Portal.Host`.
|
|
9
|
+
*
|
|
10
|
+
* ## Usage
|
|
11
|
+
* ```js
|
|
12
|
+
* import * as React from 'react';
|
|
13
|
+
* import { Text } from 'react-native';
|
|
14
|
+
* import { Portal } from 'react-native-paper';
|
|
15
|
+
*
|
|
16
|
+
* export default class MyComponent extends React.Component {
|
|
17
|
+
* render() {
|
|
18
|
+
* return (
|
|
19
|
+
* <Portal.Host>
|
|
20
|
+
* <Text>Content of the app</Text>
|
|
21
|
+
* </Portal.Host>
|
|
22
|
+
* );
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* Here any `Portal` elements under `<App />` are rendered alongside `<App />` and will appear above `<App />` like a `Modal`.
|
|
28
|
+
*/
|
|
29
|
+
export default class PortalHost extends React.Component {
|
|
30
|
+
static displayName = "Portal.Host";
|
|
31
|
+
componentDidMount() {
|
|
32
|
+
const manager = this.manager;
|
|
33
|
+
const queue = this.queue;
|
|
34
|
+
while (queue.length && manager) {
|
|
35
|
+
const action = queue.pop();
|
|
36
|
+
if (action) {
|
|
37
|
+
switch (action.type) {
|
|
38
|
+
case "mount":
|
|
39
|
+
manager.mount(action.key, action.children);
|
|
40
|
+
break;
|
|
41
|
+
case "update":
|
|
42
|
+
manager.update(action.key, action.children);
|
|
43
|
+
break;
|
|
44
|
+
case "unmount":
|
|
45
|
+
manager.unmount(action.key);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
setManager = (manager) => {
|
|
52
|
+
this.manager = manager;
|
|
53
|
+
};
|
|
54
|
+
mount = (children) => {
|
|
55
|
+
const key = this.nextKey++;
|
|
56
|
+
if (this.manager) {
|
|
57
|
+
this.manager.mount(key, children);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
this.queue.push({ type: "mount", key, children });
|
|
61
|
+
}
|
|
62
|
+
return key;
|
|
63
|
+
};
|
|
64
|
+
update = (key, children) => {
|
|
65
|
+
if (this.manager) {
|
|
66
|
+
this.manager.update(key, children);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const op = { type: "mount", key, children };
|
|
70
|
+
const index = this.queue.findIndex((o) => o.type === "mount" || (o.type === "update" && o.key === key));
|
|
71
|
+
if (index > -1) {
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
this.queue[index] = op;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.queue.push(op);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
unmount = (key) => {
|
|
81
|
+
if (this.manager) {
|
|
82
|
+
this.manager.unmount(key);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.queue.push({ type: "unmount", key });
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
nextKey = 0;
|
|
89
|
+
queue = [];
|
|
90
|
+
manager;
|
|
91
|
+
render() {
|
|
92
|
+
return (React.createElement(PortalContext.Provider, { value: {
|
|
93
|
+
mount: this.mount,
|
|
94
|
+
update: this.update,
|
|
95
|
+
unmount: this.unmount,
|
|
96
|
+
} },
|
|
97
|
+
React.createElement(View, { style: styles.container, collapsable: false, pointerEvents: "box-none" }, this.props.children),
|
|
98
|
+
React.createElement(PortalManager, { ref: this.setManager })));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const styles = StyleSheet.create({
|
|
102
|
+
container: {
|
|
103
|
+
flex: 1,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, StyleSheet } from "react-native";
|
|
3
|
+
/**
|
|
4
|
+
* Portal host is the component which actually renders all Portals.
|
|
5
|
+
*/
|
|
6
|
+
export default class PortalManager extends React.PureComponent {
|
|
7
|
+
state = {
|
|
8
|
+
portals: [],
|
|
9
|
+
};
|
|
10
|
+
mount = (key, children) => {
|
|
11
|
+
this.setState((state) => ({
|
|
12
|
+
portals: [...state.portals, { key, children }],
|
|
13
|
+
}));
|
|
14
|
+
};
|
|
15
|
+
update = (key, children) => this.setState((state) => ({
|
|
16
|
+
portals: state.portals.map((item) => {
|
|
17
|
+
if (item.key === key) {
|
|
18
|
+
return { ...item, children };
|
|
19
|
+
}
|
|
20
|
+
return item;
|
|
21
|
+
}),
|
|
22
|
+
}));
|
|
23
|
+
unmount = (key) => this.setState((state) => ({
|
|
24
|
+
portals: state.portals.filter((item) => item.key !== key),
|
|
25
|
+
}));
|
|
26
|
+
render() {
|
|
27
|
+
return this.state.portals.map(({ key, children }) => (React.createElement(View, { key: key, collapsable: false /* Need collapsable=false here to clip the elevations, otherwise they appear above sibling components */, pointerEvents: "box-none", style: StyleSheet.absoluteFill }, children)));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React, { Component } from "react";
|
|
2
|
+
import { Animated, Easing, View, I18nManager, } from "react-native";
|
|
3
|
+
const INDETERMINATE_WIDTH_FACTOR = 0.3;
|
|
4
|
+
const BAR_WIDTH_ZERO_POSITION = INDETERMINATE_WIDTH_FACTOR / (1 + INDETERMINATE_WIDTH_FACTOR);
|
|
5
|
+
export default class ProgressBar extends Component {
|
|
6
|
+
constructor(props) {
|
|
7
|
+
super(props);
|
|
8
|
+
const { progress: progressP = 0, indeterminate = false } = props;
|
|
9
|
+
const progress = Math.min(Math.max(progressP, 0), 1);
|
|
10
|
+
this.state = {
|
|
11
|
+
width: 0,
|
|
12
|
+
progress: new Animated.Value(indeterminate ? INDETERMINATE_WIDTH_FACTOR : progress),
|
|
13
|
+
animationValue: new Animated.Value(BAR_WIDTH_ZERO_POSITION),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
componentDidMount() {
|
|
17
|
+
const { indeterminate = false } = this.props;
|
|
18
|
+
if (indeterminate) {
|
|
19
|
+
this.animate();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
componentDidUpdate(prevProps) {
|
|
23
|
+
const { indeterminate = false, useNativeDriver = false, progress: progressP = 0, animationType = "spring", animationConfig = { bounciness: 0 }, animated = true, } = this.props;
|
|
24
|
+
if (prevProps.indeterminate !== indeterminate) {
|
|
25
|
+
if (indeterminate) {
|
|
26
|
+
this.animate();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
Animated.spring(this.state.animationValue, {
|
|
30
|
+
toValue: BAR_WIDTH_ZERO_POSITION,
|
|
31
|
+
useNativeDriver,
|
|
32
|
+
}).start();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (prevProps.indeterminate !== indeterminate ||
|
|
36
|
+
prevProps.progress !== progressP) {
|
|
37
|
+
const progress = this.props.indeterminate
|
|
38
|
+
? INDETERMINATE_WIDTH_FACTOR
|
|
39
|
+
: Math.min(Math.max(progressP, 0), 1);
|
|
40
|
+
if (animated) {
|
|
41
|
+
Animated[animationType](this.state.progress, {
|
|
42
|
+
...animationConfig,
|
|
43
|
+
toValue: progress,
|
|
44
|
+
velocity: 0,
|
|
45
|
+
useNativeDriver,
|
|
46
|
+
}).start();
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.state.progress.setValue(progress);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
handleLayout = (event) => {
|
|
54
|
+
const { width = 150, onLayout } = this.props;
|
|
55
|
+
if (!width) {
|
|
56
|
+
this.setState({ width: event.nativeEvent.layout.width });
|
|
57
|
+
}
|
|
58
|
+
if (onLayout) {
|
|
59
|
+
onLayout(event);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
animate() {
|
|
63
|
+
const { useNativeDriver = false, indeterminateAnimationDuration = 1000 } = this.props;
|
|
64
|
+
this.state.animationValue.setValue(0);
|
|
65
|
+
Animated.timing(this.state.animationValue, {
|
|
66
|
+
toValue: 1,
|
|
67
|
+
duration: indeterminateAnimationDuration,
|
|
68
|
+
easing: Easing.linear,
|
|
69
|
+
isInteraction: false,
|
|
70
|
+
useNativeDriver,
|
|
71
|
+
}).start((endState) => {
|
|
72
|
+
if (endState.finished) {
|
|
73
|
+
this.animate();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
render() {
|
|
78
|
+
const { borderColor, borderRadius = 4, borderWidth = 1, children, color = "rgba(0, 122, 255, 1)", style, unfilledColor, width = 150, ...restProps } = this.props;
|
|
79
|
+
const innerWidth = Math.max(0, width || this.state.width) - borderWidth * 2;
|
|
80
|
+
const containerStyle = {
|
|
81
|
+
width,
|
|
82
|
+
borderWidth,
|
|
83
|
+
borderColor: borderColor || color,
|
|
84
|
+
borderRadius,
|
|
85
|
+
overflow: "hidden",
|
|
86
|
+
backgroundColor: unfilledColor,
|
|
87
|
+
};
|
|
88
|
+
const progressStyle = {
|
|
89
|
+
backgroundColor: color,
|
|
90
|
+
// Always take up full height of container.
|
|
91
|
+
height: "100%",
|
|
92
|
+
transform: [
|
|
93
|
+
{
|
|
94
|
+
translateX: this.state.animationValue.interpolate({
|
|
95
|
+
inputRange: [0, 1],
|
|
96
|
+
outputRange: [innerWidth * -INDETERMINATE_WIDTH_FACTOR, innerWidth],
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
translateX: this.state.progress.interpolate({
|
|
101
|
+
inputRange: [0, 1],
|
|
102
|
+
outputRange: [innerWidth / (I18nManager.isRTL ? 2 : -2), 0],
|
|
103
|
+
}),
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
// Interpolation a temp workaround for https://github.com/facebook/react-native/issues/6278
|
|
107
|
+
scaleX: this.state.progress.interpolate({
|
|
108
|
+
inputRange: [0, 1],
|
|
109
|
+
outputRange: [0.0001, 1],
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
return (React.createElement(View, { style: [containerStyle, style], onLayout: this.handleLayout, ...restProps },
|
|
115
|
+
React.createElement(Animated.View, { style: progressStyle }),
|
|
116
|
+
children));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Text } from "react-native";
|
|
3
|
+
import AnimatedCircularProgress from "./AnimatedCircularProgress";
|
|
4
|
+
import { withTheme } from "../theming";
|
|
5
|
+
const ProgressCircle = ({ progress = 0.5, style, color = "primary", size = 100, showsText = true, unfilledColor, strokeCap = "butt", textStyle, thickness = 1, theme, }) => {
|
|
6
|
+
const progressNum = Math.round(progress * 100);
|
|
7
|
+
const tintColor = color || theme.colors.primary;
|
|
8
|
+
const backgroundColor = unfilledColor || theme.colors.secondary;
|
|
9
|
+
return (React.createElement(AnimatedCircularProgress, { size: size, width: thickness, backgroundWidth: thickness, fill: progressNum, tintColor: tintColor, backgroundColor: backgroundColor, rotation: 0, lineCap: strokeCap, style: style }, (fill) => showsText ? (React.createElement(Text, { style: [{ fontSize: size * 0.275, color: tintColor }, textStyle] },
|
|
10
|
+
Math.round(fill),
|
|
11
|
+
"%")) : null));
|
|
12
|
+
};
|
|
13
|
+
export default withTheme(ProgressCircle);
|