@shoutem/ui 4.6.3 → 4.6.6-rc.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/components/DateTimePicker.js +76 -18
- package/components/ListView.js +9 -5
- package/html/components/SimpleHtml.js +40 -24
- package/package.json +1 -1
- package/theme.js +2 -0
|
@@ -13,26 +13,42 @@ import { View } from './View';
|
|
|
13
13
|
|
|
14
14
|
const isIos = Platform.OS === 'ios';
|
|
15
15
|
|
|
16
|
+
export const DATEPICKER_MODES = {
|
|
17
|
+
DATE: 'date',
|
|
18
|
+
DATETIME: 'datetime',
|
|
19
|
+
TIME: 'time',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const DISPLAY_MODES = {
|
|
23
|
+
[DATEPICKER_MODES.DATE]: 'inline',
|
|
24
|
+
[DATEPICKER_MODES.DATETIME]: 'inline',
|
|
25
|
+
[DATEPICKER_MODES.TIME]: 'spinner',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function getDisplayMode(mode) {
|
|
29
|
+
if (!isIos || !Object.keys(DISPLAY_MODES).includes(mode)) {
|
|
30
|
+
return 'default';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return DISPLAY_MODES[mode];
|
|
34
|
+
}
|
|
35
|
+
|
|
16
36
|
class DateTimePicker extends PureComponent {
|
|
17
37
|
constructor(props) {
|
|
18
38
|
super(props);
|
|
19
39
|
|
|
20
40
|
autoBindReact(this);
|
|
21
41
|
|
|
42
|
+
const { mode, value } = props;
|
|
43
|
+
|
|
22
44
|
this.state = {
|
|
45
|
+
display: getDisplayMode(mode),
|
|
23
46
|
showPicker: false,
|
|
24
|
-
|
|
47
|
+
showTimePicker: false,
|
|
48
|
+
value,
|
|
25
49
|
};
|
|
26
50
|
}
|
|
27
51
|
|
|
28
|
-
componentDidUpdate() {
|
|
29
|
-
if (!isIos) {
|
|
30
|
-
const { value } = this.props;
|
|
31
|
-
|
|
32
|
-
this.setState({ value });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
52
|
handleValueChanged(event, value) {
|
|
37
53
|
if (isIos) {
|
|
38
54
|
return this.setState({ value });
|
|
@@ -42,10 +58,33 @@ class DateTimePicker extends PureComponent {
|
|
|
42
58
|
return this.handleHidePicker();
|
|
43
59
|
}
|
|
44
60
|
|
|
61
|
+
const { mode, onValueChanged } = this.props;
|
|
62
|
+
|
|
63
|
+
const showTimePicker = mode === DATEPICKER_MODES.DATETIME;
|
|
64
|
+
|
|
65
|
+
this.setState({ value, showPicker: false, showTimePicker });
|
|
66
|
+
return !showTimePicker && onValueChanged(value);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
handleTimeValueChanged(event, selectedValue) {
|
|
70
|
+
if (event.type === 'dismissed') {
|
|
71
|
+
return this.handleHidePicker();
|
|
72
|
+
}
|
|
73
|
+
|
|
45
74
|
const { onValueChanged } = this.props;
|
|
75
|
+
const { value } = this.state;
|
|
46
76
|
|
|
47
|
-
|
|
48
|
-
|
|
77
|
+
// Time picker value will override preselected date
|
|
78
|
+
// Use current date from state and only set hours & minutes
|
|
79
|
+
const currentDate = new Date(value);
|
|
80
|
+
const selectedDate = new Date(selectedValue);
|
|
81
|
+
const hour = selectedDate.getHours();
|
|
82
|
+
const minutes = selectedDate.getMinutes();
|
|
83
|
+
|
|
84
|
+
currentDate.setHours(hour, minutes, 0);
|
|
85
|
+
|
|
86
|
+
this.setState({ value: currentDate, showTimePicker: false });
|
|
87
|
+
return onValueChanged(currentDate);
|
|
49
88
|
}
|
|
50
89
|
|
|
51
90
|
handleShowPicker() {
|
|
@@ -66,6 +105,7 @@ class DateTimePicker extends PureComponent {
|
|
|
66
105
|
|
|
67
106
|
render() {
|
|
68
107
|
const {
|
|
108
|
+
cancelButtonText,
|
|
69
109
|
confirmButtonText,
|
|
70
110
|
is24Hour,
|
|
71
111
|
mode,
|
|
@@ -73,7 +113,7 @@ class DateTimePicker extends PureComponent {
|
|
|
73
113
|
style,
|
|
74
114
|
...otherProps
|
|
75
115
|
} = this.props;
|
|
76
|
-
const { showPicker, value } = this.state;
|
|
116
|
+
const { display, showPicker, showTimePicker, value } = this.state;
|
|
77
117
|
|
|
78
118
|
return (
|
|
79
119
|
<View styleName="horizontal">
|
|
@@ -82,7 +122,7 @@ class DateTimePicker extends PureComponent {
|
|
|
82
122
|
style={style.textContainer}
|
|
83
123
|
onPress={this.handleShowPicker}
|
|
84
124
|
>
|
|
85
|
-
<Text>
|
|
125
|
+
<Text>{textValue}</Text>
|
|
86
126
|
</TouchableOpacity>
|
|
87
127
|
<TouchableOpacity
|
|
88
128
|
onPress={this.handleShowPicker}
|
|
@@ -91,7 +131,7 @@ class DateTimePicker extends PureComponent {
|
|
|
91
131
|
>
|
|
92
132
|
<Icon name="drop-down" style={style.icon} />
|
|
93
133
|
</TouchableOpacity>
|
|
94
|
-
{isIos && (
|
|
134
|
+
{isIos && showPicker && (
|
|
95
135
|
<Modal
|
|
96
136
|
backdropOpacity={0.5}
|
|
97
137
|
isVisible={showPicker}
|
|
@@ -103,7 +143,7 @@ class DateTimePicker extends PureComponent {
|
|
|
103
143
|
>
|
|
104
144
|
<View styleName="md-gutter" style={style.modalContainer}>
|
|
105
145
|
<RNCDateTimePicker
|
|
106
|
-
display=
|
|
146
|
+
display={display}
|
|
107
147
|
is24Hour={is24Hour}
|
|
108
148
|
mode={mode}
|
|
109
149
|
onChange={this.handleValueChanged}
|
|
@@ -114,8 +154,14 @@ class DateTimePicker extends PureComponent {
|
|
|
114
154
|
/>
|
|
115
155
|
<View
|
|
116
156
|
style={style.modalButtonContainer}
|
|
117
|
-
styleName="md-gutter-top"
|
|
157
|
+
styleName="horizontal md-gutter-top"
|
|
118
158
|
>
|
|
159
|
+
<Button
|
|
160
|
+
style={style.modalButton}
|
|
161
|
+
onPress={this.handleHidePicker}
|
|
162
|
+
>
|
|
163
|
+
<Text>{cancelButtonText}</Text>
|
|
164
|
+
</Button>
|
|
119
165
|
<Button
|
|
120
166
|
style={style.modalButton}
|
|
121
167
|
onPress={this.handleConfirmPress}
|
|
@@ -128,7 +174,7 @@ class DateTimePicker extends PureComponent {
|
|
|
128
174
|
)}
|
|
129
175
|
{!isIos && showPicker && (
|
|
130
176
|
<RNCDateTimePicker
|
|
131
|
-
display=
|
|
177
|
+
display={display}
|
|
132
178
|
is24Hour={is24Hour}
|
|
133
179
|
mode={mode}
|
|
134
180
|
onChange={this.handleValueChanged}
|
|
@@ -136,21 +182,33 @@ class DateTimePicker extends PureComponent {
|
|
|
136
182
|
{...otherProps}
|
|
137
183
|
/>
|
|
138
184
|
)}
|
|
185
|
+
{!isIos && !showPicker && showTimePicker && (
|
|
186
|
+
<RNCDateTimePicker
|
|
187
|
+
display={display}
|
|
188
|
+
is24Hour={is24Hour}
|
|
189
|
+
mode="time"
|
|
190
|
+
onChange={this.handleTimeValueChanged}
|
|
191
|
+
value={value}
|
|
192
|
+
{...otherProps}
|
|
193
|
+
/>
|
|
194
|
+
)}
|
|
139
195
|
</View>
|
|
140
196
|
);
|
|
141
197
|
}
|
|
142
198
|
}
|
|
143
199
|
|
|
144
200
|
DateTimePicker.propTypes = {
|
|
201
|
+
cancelButtonText: PropTypes.string,
|
|
145
202
|
confirmButtonText: PropTypes.string,
|
|
146
203
|
is24Hour: PropTypes.bool,
|
|
147
|
-
mode: PropTypes.
|
|
204
|
+
mode: PropTypes.oneOf(Object.values(DATEPICKER_MODES)),
|
|
148
205
|
onValueChanged: PropTypes.func,
|
|
149
206
|
textValue: PropTypes.string,
|
|
150
207
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]),
|
|
151
208
|
};
|
|
152
209
|
|
|
153
210
|
DateTimePicker.defaultProps = {
|
|
211
|
+
cancelButtonText: 'Cancel',
|
|
154
212
|
confirmButtonText: 'Confirm',
|
|
155
213
|
is24Hour: false,
|
|
156
214
|
mode: 'datetime',
|
package/components/ListView.js
CHANGED
|
@@ -197,9 +197,9 @@ class ListView extends PureComponent {
|
|
|
197
197
|
// reference
|
|
198
198
|
mappedProps.ref = this.handleListViewRef;
|
|
199
199
|
|
|
200
|
-
mappedProps.onMomentumScrollBegin = this.
|
|
201
|
-
|
|
202
|
-
mappedProps.onMomentumScrollEnd = this.
|
|
200
|
+
mappedProps.onMomentumScrollBegin = this.setStartedScrolling;
|
|
201
|
+
|
|
202
|
+
mappedProps.onMomentumScrollEnd = this.setEndedScrolling;
|
|
203
203
|
|
|
204
204
|
return mappedProps;
|
|
205
205
|
}
|
|
@@ -221,8 +221,12 @@ class ListView extends PureComponent {
|
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
this.setState({ isScrolling });
|
|
224
|
+
setStartedScrolling() {
|
|
225
|
+
this.setState({ isScrolling: true });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
setEndedScrolling() {
|
|
229
|
+
this.setState({ isScrolling: true });
|
|
226
230
|
}
|
|
227
231
|
|
|
228
232
|
autoHideHeader({
|
|
@@ -25,6 +25,34 @@ import getEmptyObjectKeys from '../services/getEmptyObjectKeys';
|
|
|
25
25
|
import isValidVideoFormat from '../services/isValidVideoFormat';
|
|
26
26
|
import Image from './Image';
|
|
27
27
|
|
|
28
|
+
function resolveMaxWidth(style) {
|
|
29
|
+
// parentContainerPadding - padding between screen & SimpleHtml. Parent container
|
|
30
|
+
// can have it's own padding. If it does, we have to include it in calculation,
|
|
31
|
+
// otherwise maxWidth will be more than max & images will go over the edge
|
|
32
|
+
const parentContainerPadding = style.outerPadding || 0;
|
|
33
|
+
const paddingValue =
|
|
34
|
+
style.container.paddingLeft ||
|
|
35
|
+
0 + style.container.paddingRight ||
|
|
36
|
+
0 + parentContainerPadding;
|
|
37
|
+
|
|
38
|
+
return Dimensions.get('window').width - paddingValue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function resolveDimensions(objectToResize, style) {
|
|
42
|
+
const { width, height } = objectToResize;
|
|
43
|
+
|
|
44
|
+
if (!width || !height) {
|
|
45
|
+
return { width, height };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const maxWidth = resolveMaxWidth(style);
|
|
49
|
+
const objectToResizeRatio = height / width;
|
|
50
|
+
const resolvedWidth = width > maxWidth ? maxWidth : width;
|
|
51
|
+
const resolvedHeight = Math.round(resolvedWidth * objectToResizeRatio);
|
|
52
|
+
|
|
53
|
+
return { width: resolvedWidth, height: resolvedHeight };
|
|
54
|
+
}
|
|
55
|
+
|
|
28
56
|
class SimpleHtml extends PureComponent {
|
|
29
57
|
static propTypes = {
|
|
30
58
|
body: PropTypes.string,
|
|
@@ -94,23 +122,15 @@ class SimpleHtml extends PureComponent {
|
|
|
94
122
|
}
|
|
95
123
|
}
|
|
96
124
|
|
|
97
|
-
const nodeWidth =
|
|
125
|
+
const nodeWidth = node.attribs?.width;
|
|
98
126
|
|
|
99
127
|
if (!styleAttrib && !nodeWidth) {
|
|
100
128
|
return false;
|
|
101
129
|
}
|
|
102
130
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const parentContainerPadding = style.outerPadding || 0;
|
|
107
|
-
const paddingValue =
|
|
108
|
-
_.get(style, 'container.paddingLeft') * 2 + parentContainerPadding;
|
|
109
|
-
const maxWidth = Dimensions.get('window').width - paddingValue;
|
|
110
|
-
const nodeHeight = _.get(node, 'attribus.height');
|
|
111
|
-
const nodeRatio = nodeWidth / nodeHeight;
|
|
112
|
-
const resolvedWidth = nodeWidth > maxWidth ? maxWidth : nodeWidth;
|
|
113
|
-
const resolvedHeight = Math.round(resolvedWidth * nodeRatio);
|
|
131
|
+
const nodeHeight = node.attribus?.height;
|
|
132
|
+
const nodeDimensions = { width: nodeWidth, height: nodeHeight };
|
|
133
|
+
const { width, height } = resolveDimensions(nodeDimensions, style);
|
|
114
134
|
|
|
115
135
|
const nodeStyle = cssStringToObject(styleAttrib);
|
|
116
136
|
const invalidKeys = getEmptyObjectKeys(nodeStyle);
|
|
@@ -118,8 +138,8 @@ class SimpleHtml extends PureComponent {
|
|
|
118
138
|
if (invalidKeys.length || nodeWidth) {
|
|
119
139
|
const styleFiltered = _.omit(style, invalidKeys);
|
|
120
140
|
node.attribs.style = cssObjectToString(styleFiltered);
|
|
121
|
-
node.attribs.width =
|
|
122
|
-
node.attribs.height =
|
|
141
|
+
node.attribs.width = width;
|
|
142
|
+
node.attribs.height = height;
|
|
123
143
|
|
|
124
144
|
return node;
|
|
125
145
|
}
|
|
@@ -175,7 +195,7 @@ class SimpleHtml extends PureComponent {
|
|
|
175
195
|
* Currently only supports rendering image attachments.
|
|
176
196
|
*/
|
|
177
197
|
renderAttachments({ id, type }) {
|
|
178
|
-
const { attachments } = this.props;
|
|
198
|
+
const { attachments, style } = this.props;
|
|
179
199
|
|
|
180
200
|
if (!attachments) {
|
|
181
201
|
return null;
|
|
@@ -186,9 +206,11 @@ class SimpleHtml extends PureComponent {
|
|
|
186
206
|
|
|
187
207
|
if (image && image.src) {
|
|
188
208
|
const source = { uri: image.src };
|
|
189
|
-
const
|
|
209
|
+
const imageSize = { width: image.width, height: image.height };
|
|
210
|
+
const { height, width } = resolveDimensions(imageSize, style);
|
|
211
|
+
const resolvedStyle = { alignSelf: 'center', height, width };
|
|
190
212
|
|
|
191
|
-
return <Image source={source} key={id} style={
|
|
213
|
+
return <Image source={source} key={id} style={resolvedStyle} />;
|
|
192
214
|
}
|
|
193
215
|
}
|
|
194
216
|
|
|
@@ -238,13 +260,7 @@ class SimpleHtml extends PureComponent {
|
|
|
238
260
|
render() {
|
|
239
261
|
const { style, body, customTagStyles, ...otherProps } = this.props;
|
|
240
262
|
|
|
241
|
-
|
|
242
|
-
// can have it's own padding. If it does, we have to include it in calculation,
|
|
243
|
-
// otherwise maxWidth will be more than max & images will go over the edge
|
|
244
|
-
const parentContainerPadding = style.outerPadding || 0;
|
|
245
|
-
const paddingValue =
|
|
246
|
-
_.get(style, 'container.paddingLeft') * 2 + parentContainerPadding;
|
|
247
|
-
const maxWidth = Dimensions.get('window').width - paddingValue;
|
|
263
|
+
const maxWidth = resolveMaxWidth(style);
|
|
248
264
|
|
|
249
265
|
const tagStyles = {
|
|
250
266
|
...style.tags,
|
package/package.json
CHANGED
package/theme.js
CHANGED