@draftbit/core 47.0.0-alpha.1 → 47.0.0-ba694d.2
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/Stepper.js +1 -0
- package/lib/commonjs/mappings/View.js.map +1 -1
- package/lib/commonjs/mappings/WebView.js.map +1 -1
- package/lib/module/components/Stepper.js +1 -0
- package/package.json +3 -3
- 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/Banner.js +109 -0
- package/src/components/Button.js +114 -0
- package/src/components/Checkbox/Checkbox.js +63 -0
- package/src/components/Checkbox/CheckboxGroup.js +21 -0
- package/src/components/Checkbox/CheckboxGroupRow.js +77 -0
- package/src/components/Checkbox/CheckboxRow.js +78 -0
- package/src/components/Checkbox/context.js +14 -0
- package/src/components/Checkbox/index.js +3 -0
- package/src/components/Config.js +64 -0
- package/src/components/DatePicker/DatePicker.js +368 -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/Elevation.js +20 -0
- package/src/components/FormRow.js +19 -0
- package/src/components/IconButton.js +35 -0
- package/src/components/Layout.js +50 -0
- package/src/components/NumberInput.js +49 -0
- package/src/components/Picker/Picker.js +267 -0
- package/src/components/Picker/PickerComponent.android.js +69 -0
- package/src/components/Picker/PickerComponent.ios.js +79 -0
- package/src/components/Picker/PickerComponent.web.js +70 -0
- package/src/components/Picker/PickerTypes.js +1 -0
- package/src/components/Portal/Portal.js +35 -0
- package/src/components/Portal/PortalConsumer.js +27 -0
- package/src/components/Portal/PortalHost.js +107 -0
- package/src/components/Portal/PortalManager.js +32 -0
- package/src/components/RadioButton/RadioButton.js +17 -0
- package/src/components/RadioButton/RadioButtonFieldGroup.js +17 -0
- package/src/components/RadioButton/RadioButtonGroup.js +43 -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/SVG.js +13 -0
- package/src/components/ScreenContainer.js +34 -0
- package/src/components/Slider.js +63 -0
- package/src/components/StarRating.js +50 -0
- package/src/components/Stepper.js +39 -0
- package/src/components/Surface.js +32 -0
- package/src/components/Swiper/Swiper.js +29 -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 +33 -0
- package/src/components/TextField.js +428 -0
- package/src/components/Touchable.js +12 -0
- package/src/components/Touchable.web.js +2 -0
- package/src/constants.js +10 -0
- package/src/hooks.js +12 -0
- package/src/index.js +35 -0
- package/src/interfaces/Icon.js +8 -0
- package/src/mappings/Accordion.js +41 -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 +23 -0
- package/src/mappings/ActivityIndicator.js +58 -0
- package/src/mappings/AudioPlayer.js +20 -0
- package/src/mappings/BlurView.js +42 -0
- package/src/mappings/Button.js +87 -0
- package/src/mappings/Checkbox.js +46 -0
- package/src/mappings/CheckboxGroup.js +26 -0
- package/src/mappings/CheckboxRow.js +61 -0
- package/src/mappings/CustomCode.js +8 -0
- package/src/mappings/DatePicker.js +157 -0
- package/src/mappings/Fetch.js +13 -0
- package/src/mappings/FlashList.js +33 -0
- package/src/mappings/FlatList.js +24 -0
- package/src/mappings/Icon.js +32 -0
- package/src/mappings/IconButton.js +35 -0
- package/src/mappings/Image.js +35 -0
- package/src/mappings/ImageBackground.js +29 -0
- package/src/mappings/KeyboardAvoidingView.js +41 -0
- package/src/mappings/KeyboardAwareScrollView.js +50 -0
- package/src/mappings/Layout.js +200 -0
- package/src/mappings/LinearGradient.js +77 -0
- package/src/mappings/MapCallout.js +21 -0
- package/src/mappings/MapMarker.js +47 -0
- package/src/mappings/MapView.js +139 -0
- package/src/mappings/Modal.js +42 -0
- package/src/mappings/NumberInput.js +254 -0
- package/src/mappings/Picker.js +148 -0
- package/src/mappings/RadioButton.js +51 -0
- package/src/mappings/RadioButtonGroup.js +17 -0
- package/src/mappings/RadioButtonRow.js +42 -0
- package/src/mappings/SVG.js +20 -0
- package/src/mappings/SafeAreaView.js +33 -0
- package/src/mappings/ScrollView.js +31 -0
- package/src/mappings/Slider.js +60 -0
- package/src/mappings/StarRating.js +43 -0
- package/src/mappings/Stepper.js +29 -0
- package/src/mappings/Surface.js +14 -0
- package/src/mappings/Swiper.js +60 -0
- package/src/mappings/SwiperItem.js +8 -0
- package/src/mappings/Switch.js +81 -0
- package/src/mappings/Text.js +251 -0
- package/src/mappings/TextArea.js +263 -0
- package/src/mappings/TextField.js +381 -0
- package/src/mappings/TextInput.js +391 -0
- package/src/mappings/Touchable.js +17 -0
- package/src/mappings/Video.js +81 -0
- package/src/mappings/View.js +207 -0
- package/src/mappings/WebView.js +88 -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 +102 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Switch as NativeSwitch, } from "react-native";
|
|
3
|
+
import { withTheme } from "../theming";
|
|
4
|
+
import FormRow from "./FormRow";
|
|
5
|
+
import { RowDirection } from "@draftbit/types";
|
|
6
|
+
import { usePrevious } from "../hooks";
|
|
7
|
+
function Switch({ value, defaultValue, disabled, onValueChange, activeTrackColor, inactiveTrackColor, activeThumbColor, inactiveThumbColor, theme, style, ...rest }) {
|
|
8
|
+
const activeTrackThemeColor = activeTrackColor || theme.colors.primary;
|
|
9
|
+
const inactiveTrackThemeColor = inactiveTrackColor || "#EEE";
|
|
10
|
+
const activeThumbThemeColor = activeThumbColor || "#FFF";
|
|
11
|
+
const inactiveThumbThemeColor = inactiveThumbColor || "#FFF";
|
|
12
|
+
const [checked, setChecked] = React.useState(value || defaultValue);
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
if (value != null && value !== checked) {
|
|
15
|
+
setChecked(value);
|
|
16
|
+
}
|
|
17
|
+
}, [value, checked]);
|
|
18
|
+
// This special logic is to handle weird APIs like Airtable that return
|
|
19
|
+
// true or undefined for a boolean
|
|
20
|
+
const previousDefaultValue = usePrevious(defaultValue);
|
|
21
|
+
React.useEffect(() => {
|
|
22
|
+
if (defaultValue !== previousDefaultValue) {
|
|
23
|
+
setChecked(Boolean(defaultValue));
|
|
24
|
+
}
|
|
25
|
+
}, [defaultValue, previousDefaultValue]);
|
|
26
|
+
return (React.createElement(NativeSwitch, { value: checked, disabled: disabled, trackColor: {
|
|
27
|
+
false: inactiveTrackThemeColor,
|
|
28
|
+
true: activeTrackThemeColor,
|
|
29
|
+
}, thumbColor: value ? activeThumbThemeColor : inactiveThumbThemeColor,
|
|
30
|
+
// @ts-ignore react-native-web only
|
|
31
|
+
activeThumbColor: activeThumbThemeColor, ios_backgroundColor: inactiveTrackThemeColor, style: style, onValueChange: (bool) => {
|
|
32
|
+
setChecked(bool);
|
|
33
|
+
onValueChange && onValueChange(bool);
|
|
34
|
+
}, ...rest }));
|
|
35
|
+
}
|
|
36
|
+
function Row({ label = "Label", direction = RowDirection.Row, style, value, defaultValue, disabled, onValueChange, activeTrackColor, inactiveTrackColor, activeThumbColor, inactiveThumbColor, theme, ...rest }) {
|
|
37
|
+
const [checked, setChecked] = React.useState(value != null ? value : defaultValue);
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
if (value != null) {
|
|
40
|
+
setChecked(value);
|
|
41
|
+
}
|
|
42
|
+
}, [value]);
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
if (defaultValue != null) {
|
|
45
|
+
setChecked(defaultValue);
|
|
46
|
+
}
|
|
47
|
+
}, [defaultValue]);
|
|
48
|
+
return (React.createElement(FormRow, { disabled: disabled, onPress: () => {
|
|
49
|
+
setChecked(!checked);
|
|
50
|
+
onValueChange && onValueChange(!checked);
|
|
51
|
+
}, label: label, direction: direction, style: style, ...rest },
|
|
52
|
+
React.createElement(Switch, { theme: theme, value: checked, disabled: disabled, onValueChange: onValueChange, activeTrackColor: activeTrackColor, inactiveTrackColor: inactiveTrackColor, activeThumbColor: activeThumbColor, inactiveThumbColor: inactiveThumbColor })));
|
|
53
|
+
}
|
|
54
|
+
const SwitchRow = withTheme(Row);
|
|
55
|
+
export { SwitchRow };
|
|
56
|
+
export default withTheme(Switch);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Text as NativeText, I18nManager } from "react-native";
|
|
3
|
+
import { withTheme } from "../theming";
|
|
4
|
+
class Text extends React.Component {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.state = {
|
|
8
|
+
nativeProps: {},
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
setNativeProps(args) {
|
|
12
|
+
this.state.nativeProps = args || {};
|
|
13
|
+
}
|
|
14
|
+
render() {
|
|
15
|
+
const { style, ...rest } = this.props;
|
|
16
|
+
const writingDirection = I18nManager.isRTL ? "rtl" : "ltr";
|
|
17
|
+
return (React.createElement(NativeText, { ...rest, ...this.state.nativeProps, ref: (c) => {
|
|
18
|
+
this._root = c;
|
|
19
|
+
}, style: [
|
|
20
|
+
{
|
|
21
|
+
textAlign: "left",
|
|
22
|
+
writingDirection,
|
|
23
|
+
},
|
|
24
|
+
style,
|
|
25
|
+
] }));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export const BaseLink = ({ style, theme, title, ...props }) => {
|
|
29
|
+
return (React.createElement(Text, { hitSlop: 8, style: [{ color: theme.colors.primary }, style], theme: theme, ...props }, title));
|
|
30
|
+
};
|
|
31
|
+
const Link = withTheme(BaseLink);
|
|
32
|
+
export { Link };
|
|
33
|
+
export default withTheme(Text);
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, Animated, TextInput as NativeTextInput, StyleSheet, Text, I18nManager, } from "react-native";
|
|
3
|
+
import { withTheme } from "../theming";
|
|
4
|
+
import { applyStyles, extractStyles } from "../utilities";
|
|
5
|
+
const AnimatedText = Animated.createAnimatedComponent(Text);
|
|
6
|
+
const FOCUS_ANIMATION_DURATION = 150;
|
|
7
|
+
const BLUR_ANIMATION_DURATION = 180;
|
|
8
|
+
const ICON_SIZE = 24;
|
|
9
|
+
class TextField extends React.Component {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.state = {
|
|
13
|
+
nativeProps: {},
|
|
14
|
+
labeled: new Animated.Value(this.props.value || this.props.error ? 0 : 1),
|
|
15
|
+
focused: false,
|
|
16
|
+
placeholder: this.props.error ? this.props.placeholder : "",
|
|
17
|
+
labelLayout: {
|
|
18
|
+
measured: false,
|
|
19
|
+
width: 0,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
this._timer = setTimeout(() => { }, 0);
|
|
23
|
+
this._showPlaceholder = () => {
|
|
24
|
+
clearTimeout(this._timer);
|
|
25
|
+
// Set the placeholder in a delay to offset the label animation
|
|
26
|
+
// If we show it immediately, they'll overlap and look ugly
|
|
27
|
+
this._timer = setTimeout(() => this.setState({
|
|
28
|
+
placeholder: this.props.placeholder,
|
|
29
|
+
}), 50);
|
|
30
|
+
};
|
|
31
|
+
this._hidePlaceholder = () => this.setState({
|
|
32
|
+
placeholder: "",
|
|
33
|
+
});
|
|
34
|
+
this._restoreLabel = () => Animated.timing(this.state.labeled, {
|
|
35
|
+
toValue: 1,
|
|
36
|
+
duration: FOCUS_ANIMATION_DURATION,
|
|
37
|
+
useNativeDriver: true,
|
|
38
|
+
}).start();
|
|
39
|
+
this._minmizeLabel = () => Animated.timing(this.state.labeled, {
|
|
40
|
+
toValue: 0,
|
|
41
|
+
duration: BLUR_ANIMATION_DURATION,
|
|
42
|
+
useNativeDriver: true,
|
|
43
|
+
}).start();
|
|
44
|
+
this._handleFocus = () => {
|
|
45
|
+
if (this.props.disabled) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.setState({ focused: true });
|
|
49
|
+
};
|
|
50
|
+
this._handleBlur = () => {
|
|
51
|
+
if (this.props.disabled) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
this.setState({ focused: false });
|
|
55
|
+
};
|
|
56
|
+
this._handleChangeText = (value) => {
|
|
57
|
+
if (this.props.disabled) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (typeof value === "string") {
|
|
61
|
+
this.setState({ value });
|
|
62
|
+
this.props.onChangeText && this.props.onChangeText(value);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
this.setState({ value: value.nativeEvent.text });
|
|
66
|
+
this.props.onChangeText &&
|
|
67
|
+
this.props.onChangeText(value.nativeEvent.text);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
this._root = undefined;
|
|
71
|
+
}
|
|
72
|
+
static getDerivedStateFromProps(nextProps, prevState) {
|
|
73
|
+
return {
|
|
74
|
+
value: typeof nextProps.value !== "undefined"
|
|
75
|
+
? nextProps.value
|
|
76
|
+
: prevState.value,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
componentDidMount() {
|
|
80
|
+
if (this.props.defaultValue) {
|
|
81
|
+
this._handleChangeText(this.props.defaultValue);
|
|
82
|
+
}
|
|
83
|
+
if (this.props.placeholder) {
|
|
84
|
+
this._minmizeLabel();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
componentDidUpdate(prevProps, prevState) {
|
|
88
|
+
if (prevState.focused !== this.state.focused ||
|
|
89
|
+
prevState.value !== this.state.value) {
|
|
90
|
+
// The label should be minimized if the text input is focused, or has text
|
|
91
|
+
// In minimized mode, the label moves up and becomes small
|
|
92
|
+
if (this.state.value ||
|
|
93
|
+
this.state.focused ||
|
|
94
|
+
this.props.error ||
|
|
95
|
+
this.props.placeholder) {
|
|
96
|
+
this._minmizeLabel();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this._restoreLabel();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (prevState.focused !== this.state.focused ||
|
|
103
|
+
prevProps.label !== this.props.label) {
|
|
104
|
+
// Show placeholder text only if the input is focused, or has error, or there's no label
|
|
105
|
+
// We don't show placeholder if there's a label because the label acts as placeholder
|
|
106
|
+
// When focused, the label moves up, so we can show a placeholder
|
|
107
|
+
if (this.state.focused || this.props.error || !this.props.label) {
|
|
108
|
+
this._showPlaceholder();
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this._hidePlaceholder();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
componentWillUnmount() {
|
|
116
|
+
clearTimeout(this._timer);
|
|
117
|
+
}
|
|
118
|
+
toggleFocus() {
|
|
119
|
+
this.setState((prevState) => ({ focused: !prevState.focused }));
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* @internal
|
|
123
|
+
*/
|
|
124
|
+
setNativeProps(args) {
|
|
125
|
+
this.setState((state) => ({
|
|
126
|
+
...state,
|
|
127
|
+
nativeState: args || {},
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
isFocused() {
|
|
131
|
+
return this._root && this._root.isFocused();
|
|
132
|
+
}
|
|
133
|
+
clear() {
|
|
134
|
+
return this._root && this._root.clear();
|
|
135
|
+
}
|
|
136
|
+
focus() {
|
|
137
|
+
return this._root && this._root.focus();
|
|
138
|
+
}
|
|
139
|
+
blur() {
|
|
140
|
+
return this._root && this._root.blur();
|
|
141
|
+
}
|
|
142
|
+
render() {
|
|
143
|
+
const { Icon, type = "underline", disabled = false, label, error = false, leftIconName, leftIconMode, rightIconName, assistiveText, underlineColor: underlineColorProp, activeBorderColor: activeBorderColorProp, multiline = false, numberOfLines = 4, style, theme: { colors, typography, roundness, disabledOpacity }, render = (props) => React.createElement(NativeTextInput, { ...props }), ...rest } = this.props;
|
|
144
|
+
const MINIMIZED_LABEL_Y_OFFSET = -(typography.caption.lineHeight + 4);
|
|
145
|
+
const OUTLINE_MINIMIZED_LABEL_Y_OFFSET = -(16 * 0.5 + 4);
|
|
146
|
+
const MAXIMIZED_LABEL_FONT_SIZE = typography.subtitle1.fontSize;
|
|
147
|
+
const MINIMIZED_LABEL_FONT_SIZE = typography.caption.fontSize;
|
|
148
|
+
const hasActiveOutline = this.state.focused || error;
|
|
149
|
+
let inputTextColor, activeColor, underlineColor, borderColor, placeholderColor, containerStyle, backgroundColor, inputStyle;
|
|
150
|
+
inputTextColor = colors.strong;
|
|
151
|
+
if (disabled) {
|
|
152
|
+
activeColor = colors.light;
|
|
153
|
+
placeholderColor = colors.light;
|
|
154
|
+
borderColor = "transparent";
|
|
155
|
+
underlineColor = "transparent";
|
|
156
|
+
backgroundColor = colors.divider;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
activeColor = error ? colors.error : activeBorderColorProp;
|
|
160
|
+
placeholderColor = borderColor = colors.light;
|
|
161
|
+
underlineColor = underlineColorProp;
|
|
162
|
+
backgroundColor = colors.background;
|
|
163
|
+
}
|
|
164
|
+
if (rest.placeholderTextColor) {
|
|
165
|
+
placeholderColor = rest.placeholderTextColor;
|
|
166
|
+
}
|
|
167
|
+
const { lineHeight, ...subtitle1 } = typography.subtitle1;
|
|
168
|
+
inputStyle = {
|
|
169
|
+
paddingVertical: 0,
|
|
170
|
+
color: inputTextColor,
|
|
171
|
+
paddingLeft: leftIconName && leftIconMode === "inset"
|
|
172
|
+
? ICON_SIZE + 12 + (type === "solid" ? 16 : 0)
|
|
173
|
+
: 0,
|
|
174
|
+
paddingRight: rightIconName ? ICON_SIZE + 16 + 4 : 12,
|
|
175
|
+
...subtitle1,
|
|
176
|
+
};
|
|
177
|
+
if (!multiline) {
|
|
178
|
+
inputStyle.height = lineHeight;
|
|
179
|
+
}
|
|
180
|
+
let assistiveTextLeftMargin;
|
|
181
|
+
if (type === "underline") {
|
|
182
|
+
containerStyle = {
|
|
183
|
+
borderTopLeftRadius: roundness,
|
|
184
|
+
borderTopRightRadius: roundness,
|
|
185
|
+
paddingBottom: 12,
|
|
186
|
+
marginTop: 16,
|
|
187
|
+
};
|
|
188
|
+
if (leftIconName && leftIconMode === "outset") {
|
|
189
|
+
assistiveTextLeftMargin = ICON_SIZE + 8;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
assistiveTextLeftMargin = 0;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
containerStyle = {
|
|
197
|
+
borderRadius: roundness,
|
|
198
|
+
borderColor: hasActiveOutline ? activeColor : borderColor,
|
|
199
|
+
borderWidth: 1,
|
|
200
|
+
paddingTop: label ? 16 * 1.5 : 16,
|
|
201
|
+
paddingBottom: label ? 16 * 0.5 : 16,
|
|
202
|
+
opacity: disabled ? disabledOpacity : 1,
|
|
203
|
+
backgroundColor,
|
|
204
|
+
};
|
|
205
|
+
if (leftIconName && leftIconMode === "inset") {
|
|
206
|
+
assistiveTextLeftMargin = 16 + 4;
|
|
207
|
+
}
|
|
208
|
+
else if (leftIconName && leftIconMode === "outset") {
|
|
209
|
+
assistiveTextLeftMargin = ICON_SIZE + 8 + 12;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
assistiveTextLeftMargin = 12;
|
|
213
|
+
}
|
|
214
|
+
inputStyle.paddingHorizontal = 12;
|
|
215
|
+
}
|
|
216
|
+
if (leftIconName && leftIconMode === "outset") {
|
|
217
|
+
containerStyle.marginLeft = ICON_SIZE + 8;
|
|
218
|
+
}
|
|
219
|
+
let leftIconColor;
|
|
220
|
+
if (error) {
|
|
221
|
+
leftIconColor = colors.error;
|
|
222
|
+
}
|
|
223
|
+
else if (this.state.focused) {
|
|
224
|
+
leftIconColor = colors.primary;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
leftIconColor = colors.light;
|
|
228
|
+
}
|
|
229
|
+
const leftIconProps = {
|
|
230
|
+
size: 24,
|
|
231
|
+
color: leftIconColor,
|
|
232
|
+
name: leftIconName || "",
|
|
233
|
+
};
|
|
234
|
+
const leftIconStyle = {
|
|
235
|
+
position: "absolute",
|
|
236
|
+
marginTop: type === "solid"
|
|
237
|
+
? MINIMIZED_LABEL_FONT_SIZE + 4
|
|
238
|
+
: leftIconMode === "outset"
|
|
239
|
+
? 16
|
|
240
|
+
: 0,
|
|
241
|
+
marginLeft: leftIconMode === "inset" && type === "solid" ? 16 : 0,
|
|
242
|
+
};
|
|
243
|
+
const labelStyle = {
|
|
244
|
+
...typography.subtitle1,
|
|
245
|
+
top: type === "solid" ? 16 : 0,
|
|
246
|
+
left: leftIconName && leftIconMode === "inset"
|
|
247
|
+
? ICON_SIZE + (type === "solid" ? 16 : 12)
|
|
248
|
+
: 0,
|
|
249
|
+
transform: [
|
|
250
|
+
{
|
|
251
|
+
// Move label to top
|
|
252
|
+
translateY: this.state.labeled.interpolate({
|
|
253
|
+
inputRange: [0, 1],
|
|
254
|
+
outputRange: [
|
|
255
|
+
type === "solid"
|
|
256
|
+
? OUTLINE_MINIMIZED_LABEL_Y_OFFSET
|
|
257
|
+
: MINIMIZED_LABEL_Y_OFFSET,
|
|
258
|
+
0,
|
|
259
|
+
],
|
|
260
|
+
}),
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
// Make label smaller
|
|
264
|
+
scale: this.state.labeled.interpolate({
|
|
265
|
+
inputRange: [0, 1],
|
|
266
|
+
outputRange: [
|
|
267
|
+
MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE,
|
|
268
|
+
1,
|
|
269
|
+
],
|
|
270
|
+
}),
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
// Offset label scale since RN doesn't support transform origin
|
|
274
|
+
translateX: this.state.labeled.interpolate({
|
|
275
|
+
inputRange: [0, 1],
|
|
276
|
+
outputRange: [
|
|
277
|
+
-(1 - MINIMIZED_LABEL_FONT_SIZE / MAXIMIZED_LABEL_FONT_SIZE) *
|
|
278
|
+
(this.state.labelLayout.width / 2),
|
|
279
|
+
0,
|
|
280
|
+
],
|
|
281
|
+
}),
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
};
|
|
285
|
+
const { textStyles } = extractStyles(style);
|
|
286
|
+
const inputStyles = applyStyles([
|
|
287
|
+
styles.input,
|
|
288
|
+
inputStyle,
|
|
289
|
+
type === "solid" ? { marginHorizontal: 12 } : {},
|
|
290
|
+
], textStyles);
|
|
291
|
+
const { backgroundColor: bgColor, padding, paddingTop, paddingBottom, paddingLeft, paddingRight, borderRadius, borderWidth, borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, borderColor: borderCol, ...styleProp } = StyleSheet.flatten(style || {});
|
|
292
|
+
return (React.createElement(View, { style: [styles.container, styleProp] },
|
|
293
|
+
leftIconName && leftIconMode === "outset" ? (React.createElement(Icon, { ...leftIconProps, style: leftIconStyle })) : null,
|
|
294
|
+
React.createElement(View, { style: applyStyles([containerStyle], {
|
|
295
|
+
height: style === null || style === void 0 ? void 0 : style.height,
|
|
296
|
+
backgroundColor: bgColor,
|
|
297
|
+
padding,
|
|
298
|
+
paddingTop,
|
|
299
|
+
paddingBottom,
|
|
300
|
+
paddingLeft,
|
|
301
|
+
paddingRight,
|
|
302
|
+
borderRadius,
|
|
303
|
+
borderWidth,
|
|
304
|
+
borderTopWidth,
|
|
305
|
+
borderRightWidth,
|
|
306
|
+
borderBottomWidth,
|
|
307
|
+
borderLeftWidth,
|
|
308
|
+
borderColor: borderCol,
|
|
309
|
+
}) },
|
|
310
|
+
type === "underline" ? (
|
|
311
|
+
// When type === 'flat', render an underline
|
|
312
|
+
React.createElement(Animated.View, { style: [
|
|
313
|
+
styles.underline,
|
|
314
|
+
{
|
|
315
|
+
backgroundColor: bgColor ||
|
|
316
|
+
(error
|
|
317
|
+
? colors.error
|
|
318
|
+
: this.state.focused
|
|
319
|
+
? activeColor
|
|
320
|
+
: underlineColor),
|
|
321
|
+
// Underlines is thinner when input is not focused
|
|
322
|
+
transform: [{ scaleY: this.state.focused ? 1 : 0.5 }],
|
|
323
|
+
},
|
|
324
|
+
] })) : null,
|
|
325
|
+
label ? (
|
|
326
|
+
// Position colored placeholder and gray placeholder on top of each other and crossfade them
|
|
327
|
+
// This gives the effect of animating the color, but allows us to use native driver
|
|
328
|
+
React.createElement(View, { pointerEvents: "none", style: [
|
|
329
|
+
StyleSheet.absoluteFill,
|
|
330
|
+
{
|
|
331
|
+
opacity:
|
|
332
|
+
// Hide the label in minimized state until we measure its width
|
|
333
|
+
this.state.value || this.state.focused
|
|
334
|
+
? this.state.labelLayout.measured
|
|
335
|
+
? 1
|
|
336
|
+
: 0
|
|
337
|
+
: 1,
|
|
338
|
+
},
|
|
339
|
+
] },
|
|
340
|
+
React.createElement(AnimatedText, { onLayout: (e) => this.setState({
|
|
341
|
+
labelLayout: {
|
|
342
|
+
width: e.nativeEvent.layout.width,
|
|
343
|
+
measured: true,
|
|
344
|
+
},
|
|
345
|
+
}), style: [
|
|
346
|
+
styles.placeholder,
|
|
347
|
+
type === "solid" ? { paddingHorizontal: 12 } : {},
|
|
348
|
+
labelStyle,
|
|
349
|
+
{
|
|
350
|
+
color: placeholderColor,
|
|
351
|
+
opacity: this.state.labeled.interpolate({
|
|
352
|
+
inputRange: [0, 1],
|
|
353
|
+
outputRange: [hasActiveOutline ? 1 : 0, 0],
|
|
354
|
+
}),
|
|
355
|
+
},
|
|
356
|
+
], numberOfLines: 1 }, label),
|
|
357
|
+
React.createElement(AnimatedText, { style: [
|
|
358
|
+
styles.placeholder,
|
|
359
|
+
type === "solid" ? { paddingHorizontal: 12 } : {},
|
|
360
|
+
labelStyle,
|
|
361
|
+
{
|
|
362
|
+
color: placeholderColor,
|
|
363
|
+
opacity: hasActiveOutline ? this.state.labeled : 1,
|
|
364
|
+
},
|
|
365
|
+
], numberOfLines: 1 }, label))) : null,
|
|
366
|
+
leftIconName && leftIconMode === "inset" ? (React.createElement(View, { style: {
|
|
367
|
+
justifyContent: type === "solid" ? "center" : undefined,
|
|
368
|
+
} },
|
|
369
|
+
React.createElement(Icon, { ...leftIconProps, style: leftIconStyle }))) : null,
|
|
370
|
+
render({
|
|
371
|
+
ref: (c) => {
|
|
372
|
+
this._root = c;
|
|
373
|
+
},
|
|
374
|
+
onChange: this._handleChangeText,
|
|
375
|
+
placeholder: label
|
|
376
|
+
? this.state.placeholder
|
|
377
|
+
: this.props.placeholder,
|
|
378
|
+
placeholderTextColor: placeholderColor,
|
|
379
|
+
editable: !disabled,
|
|
380
|
+
selectionColor: activeColor,
|
|
381
|
+
multiline,
|
|
382
|
+
numberOfLines,
|
|
383
|
+
onFocus: this._handleFocus,
|
|
384
|
+
onBlur: this._handleBlur,
|
|
385
|
+
underlineColorAndroid: "transparent",
|
|
386
|
+
style: inputStyles,
|
|
387
|
+
...rest,
|
|
388
|
+
...this.state.nativeProps,
|
|
389
|
+
value: this.state.value,
|
|
390
|
+
})),
|
|
391
|
+
rightIconName ? (React.createElement(Icon, { name: rightIconName, size: ICON_SIZE, color: colors.light, style: {
|
|
392
|
+
position: "absolute",
|
|
393
|
+
right: 16,
|
|
394
|
+
marginTop: type === "solid" ? MINIMIZED_LABEL_FONT_SIZE + 4 : 16,
|
|
395
|
+
} })) : null,
|
|
396
|
+
assistiveText ? (React.createElement(Text, { style: [
|
|
397
|
+
{
|
|
398
|
+
color: error ? colors.error : colors.light,
|
|
399
|
+
marginTop: 8,
|
|
400
|
+
marginLeft: assistiveTextLeftMargin,
|
|
401
|
+
},
|
|
402
|
+
] }, assistiveText)) : null));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
export default withTheme(TextField);
|
|
406
|
+
const styles = StyleSheet.create({
|
|
407
|
+
container: {
|
|
408
|
+
alignSelf: "stretch",
|
|
409
|
+
},
|
|
410
|
+
placeholder: {
|
|
411
|
+
position: "absolute",
|
|
412
|
+
left: 0,
|
|
413
|
+
},
|
|
414
|
+
underline: {
|
|
415
|
+
position: "absolute",
|
|
416
|
+
left: 0,
|
|
417
|
+
right: 0,
|
|
418
|
+
bottom: 0,
|
|
419
|
+
height: 2,
|
|
420
|
+
},
|
|
421
|
+
input: {
|
|
422
|
+
flexGrow: 1,
|
|
423
|
+
justifyContent: "center",
|
|
424
|
+
textAlignVertical: "center",
|
|
425
|
+
margin: 0,
|
|
426
|
+
textAlign: I18nManager.isRTL ? "right" : "left",
|
|
427
|
+
},
|
|
428
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Pressable } from "react-native";
|
|
3
|
+
export default function Touchable({ children, disabled, onPress, style, ...props }) {
|
|
4
|
+
return (React.createElement(Pressable, { onPress: onPress, disabled: disabled, hitSlop: 8, style: ({ pressed }) => {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
opacity: pressed || disabled ? 0.75 : 1,
|
|
8
|
+
},
|
|
9
|
+
style,
|
|
10
|
+
];
|
|
11
|
+
}, ...props }, children));
|
|
12
|
+
}
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Platform } from "react-native";
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
const expo = global.__expo;
|
|
4
|
+
const DEFAULT_STATUSBAR_HEIGHT_EXPO = (expo === null || expo === void 0 ? void 0 : expo.Constants)
|
|
5
|
+
? expo.Constants.statusBarHeight
|
|
6
|
+
: 0;
|
|
7
|
+
export const APPROX_STATUSBAR_HEIGHT = Platform.select({
|
|
8
|
+
android: DEFAULT_STATUSBAR_HEIGHT_EXPO,
|
|
9
|
+
ios: Platform.Version < 11 ? DEFAULT_STATUSBAR_HEIGHT_EXPO : 0,
|
|
10
|
+
});
|
package/src/hooks.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export function usePrevious(value) {
|
|
3
|
+
// The ref object is a generic container whose current property is mutable
|
|
4
|
+
// and can hold any value, similar to an instance property on a class
|
|
5
|
+
const ref = React.useRef();
|
|
6
|
+
// Store current value in ref
|
|
7
|
+
React.useEffect(() => {
|
|
8
|
+
ref.current = value;
|
|
9
|
+
}, [value]);
|
|
10
|
+
// Return previous value (happens before update in useEffect above)
|
|
11
|
+
return ref.current;
|
|
12
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export { injectIcon } from "./interfaces/Icon";
|
|
2
|
+
export { withTheme, ThemeProvider } from "./theming";
|
|
3
|
+
export { default as Provider } from "./Provider";
|
|
4
|
+
export { default as DefaultTheme } from "./styles/DefaultTheme";
|
|
5
|
+
// BASIC
|
|
6
|
+
export { default as ScreenContainer } from "./components/ScreenContainer";
|
|
7
|
+
export { default as Banner } from "./components/Banner";
|
|
8
|
+
// BUTTONS
|
|
9
|
+
export { Button } from "./components/Button";
|
|
10
|
+
export { Link } from "./components/Text";
|
|
11
|
+
export { default as IconButton } from "./components/IconButton";
|
|
12
|
+
export { default as Touchable } from "./components/Touchable";
|
|
13
|
+
// INPUTS
|
|
14
|
+
export { default as DatePicker } from "./components/DatePicker/DatePicker";
|
|
15
|
+
export { default as NumberInput } from "./components/NumberInput";
|
|
16
|
+
export { default as TextField } from "./components/TextField";
|
|
17
|
+
export { default as Picker } from "./components/Picker/Picker";
|
|
18
|
+
// CONTROLS
|
|
19
|
+
export { Checkbox, CheckboxGroup, CheckboxRow } from "./components/Checkbox";
|
|
20
|
+
export { RadioButton, RadioButtonGroup, RadioButtonRow, RadioButtonFieldGroup, } from "./components/RadioButton/index";
|
|
21
|
+
export { default as Slider } from "./components/Slider";
|
|
22
|
+
export { default as Stepper } from "./components/Stepper";
|
|
23
|
+
export { default as StarRating } from "./components/StarRating";
|
|
24
|
+
export { default as Switch, SwitchRow } from "./components/Switch";
|
|
25
|
+
// MEDIA
|
|
26
|
+
export { default as SVG } from "./components/SVG";
|
|
27
|
+
// FLEX LAYOUT
|
|
28
|
+
export { Center, Circle, Square, Row, Stack, Spacer, } from "./components/Layout";
|
|
29
|
+
// SWIPER
|
|
30
|
+
export { Swiper, SwiperItem } from "./components/Swiper";
|
|
31
|
+
// CONTAINERS
|
|
32
|
+
export { AccordionGroup, AccordionItem } from "./components/Accordion";
|
|
33
|
+
export { default as Surface } from "./components/Surface";
|
|
34
|
+
// ACTIONSHEET
|
|
35
|
+
export { ActionSheet, ActionSheetItem, ActionSheetCancel, } from "./components/ActionSheet";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is an interface for a hybrid component.
|
|
3
|
+
*
|
|
4
|
+
* Its public implementation is `@draftbit/native`, and it is injected inside
|
|
5
|
+
* `@draftbit/ui`.
|
|
6
|
+
*/
|
|
7
|
+
import React from "react";
|
|
8
|
+
export const injectIcon = (Component, Icon) => (props) => React.createElement(Component, { ...props, Icon });
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { COMPONENT_TYPES, createNumberProp, createIconProp, createTextProp, createStaticBoolProp, createColorProp, } from "@draftbit/types";
|
|
2
|
+
export const SEED_DATA = {
|
|
3
|
+
name: "Accordion",
|
|
4
|
+
tag: "AccordionGroup",
|
|
5
|
+
description: "An expandable container containing components",
|
|
6
|
+
category: COMPONENT_TYPES.container,
|
|
7
|
+
layout: {
|
|
8
|
+
paddingTop: 8,
|
|
9
|
+
paddingRight: 8,
|
|
10
|
+
paddingBottom: 8,
|
|
11
|
+
paddingLeft: 8,
|
|
12
|
+
fontSize: 16,
|
|
13
|
+
},
|
|
14
|
+
props: {
|
|
15
|
+
label: createTextProp({
|
|
16
|
+
label: "Label",
|
|
17
|
+
}),
|
|
18
|
+
expanded: createStaticBoolProp({
|
|
19
|
+
label: "Expanded",
|
|
20
|
+
description: "Whether the AccordionGroup should be initaially expanded or not",
|
|
21
|
+
}),
|
|
22
|
+
openColor: createColorProp({
|
|
23
|
+
label: "Open text color",
|
|
24
|
+
}),
|
|
25
|
+
closedColor: createColorProp({
|
|
26
|
+
label: "Closed text color",
|
|
27
|
+
}),
|
|
28
|
+
caretColor: createColorProp({
|
|
29
|
+
label: "Caret color",
|
|
30
|
+
}),
|
|
31
|
+
caretSize: createNumberProp({
|
|
32
|
+
label: "Caret size",
|
|
33
|
+
defaultValue: 24,
|
|
34
|
+
}),
|
|
35
|
+
icon: createIconProp(),
|
|
36
|
+
iconSize: createNumberProp({
|
|
37
|
+
label: "Icon size",
|
|
38
|
+
defaultValue: 24,
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { COMPONENT_TYPES, createIconProp, createTextProp, createColorProp, } from "@draftbit/types";
|
|
2
|
+
export const SEED_DATA = {
|
|
3
|
+
name: "Accordion Item",
|
|
4
|
+
tag: "AccordionItem",
|
|
5
|
+
description: "Item to be used in Accordion",
|
|
6
|
+
category: COMPONENT_TYPES.deprecated,
|
|
7
|
+
props: {
|
|
8
|
+
icon: createIconProp(),
|
|
9
|
+
label: createTextProp({
|
|
10
|
+
label: "Item label",
|
|
11
|
+
}),
|
|
12
|
+
iconColor: createColorProp({
|
|
13
|
+
label: "Icon color",
|
|
14
|
+
}),
|
|
15
|
+
},
|
|
16
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { COMPONENT_TYPES, createStaticBoolProp, GROUPS } from "@draftbit/types";
|
|
2
|
+
export const SEED_DATA = {
|
|
3
|
+
name: "Action Sheet",
|
|
4
|
+
tag: "ActionSheet",
|
|
5
|
+
description: "Action Sheet container",
|
|
6
|
+
category: COMPONENT_TYPES.actionsheet,
|
|
7
|
+
props: {
|
|
8
|
+
visible: createStaticBoolProp({
|
|
9
|
+
group: GROUPS.data,
|
|
10
|
+
label: "Show Action Sheet",
|
|
11
|
+
}),
|
|
12
|
+
},
|
|
13
|
+
};
|