5
5
ImageStyle ,
6
6
StyleProp ,
7
7
StyleSheet ,
8
+ TextStyle ,
8
9
TouchableOpacity ,
9
10
TouchableOpacityProps ,
10
11
View ,
@@ -20,43 +21,70 @@ import {
20
21
Text ,
21
22
TextElement ,
22
23
} from '../text/text.component' ;
24
+ import { IconElement } from '../icon/icon.component' ;
23
25
import { Popover } from '../popover/popover.component' ;
24
26
import { BaseCalendarProps } from '../calendar/baseCalendar.component' ;
25
- import { NativeDateService } from '../calendar/service/nativeDate.service' ;
26
27
import { CalendarElement } from '../calendar/calendar.component' ;
27
28
import { RangeCalendarElement } from '../calendar/rangeCalendar.component' ;
28
- import { PopoverPlacements } from '../popover/type' ;
29
+ import { NativeDateService } from '../calendar/service/nativeDate.service' ;
30
+ import { isValidString } from '../support/services' ;
31
+ import {
32
+ PopoverPlacement ,
33
+ PopoverPlacements ,
34
+ } from '../popover/type' ;
35
+
36
+ type IconProp = ( style : StyleType ) => IconElement ;
37
+
29
38
30
39
export interface BaseDatepickerProps < D = Date > extends StyledComponentProps ,
31
40
TouchableOpacityProps ,
32
41
BaseCalendarProps < D > {
33
42
34
43
controlStyle ?: StyleProp < ViewStyle > ;
44
+ label ?: string ;
45
+ caption ?: string ;
46
+ captionIcon ?: IconProp ;
35
47
icon ?: ( style : ImageStyle ) => React . ReactElement < ImageProps > ;
36
48
status ?: string ;
37
49
size ?: string ;
38
50
placeholder ?: string ;
51
+ labelStyle ?: StyleProp < TextStyle > ;
52
+ captionStyle ?: StyleProp < TextStyle > ;
53
+ placement ?: PopoverPlacement | string ;
39
54
}
40
55
41
56
interface State {
42
57
visible : boolean ;
43
58
}
44
59
45
- type DatepickerChildren < D = Date > = [ CalendarElement < D > , React . ReactElement ] ;
46
-
47
60
const FULL_DATE_FORMAT_STRING : string = 'DD/MM/YYYY' ;
48
61
49
62
export abstract class BaseDatepickerComponent < P , D = Date > extends React . Component < BaseDatepickerProps < D > & P , State > {
50
63
51
64
static defaultProps : Partial < BaseDatepickerProps > = {
52
65
dateService : new NativeDateService ( ) ,
53
66
placeholder : 'dd/mm/yyyy' ,
67
+ placement : PopoverPlacements . BOTTOM_START ,
54
68
} ;
55
69
56
70
public state : State = {
57
71
visible : false ,
58
72
} ;
59
73
74
+ public focus = ( ) : void => {
75
+ this . setState ( { visible : true } , this . dispatchActive ) ;
76
+ } ;
77
+
78
+ public blur = ( ) : void => {
79
+ this . setState ( { visible : true } , this . dispatchActive ) ;
80
+ } ;
81
+
82
+ public isFocused = ( ) : boolean => {
83
+ return this . state . visible ;
84
+ } ;
85
+
86
+ public abstract clear ( ) : void ;
87
+
60
88
protected abstract getComponentTitle ( ) : string ;
61
89
62
90
protected abstract renderCalendar ( ) : CalendarElement < D > | RangeCalendarElement < D > ;
@@ -67,40 +95,86 @@ export abstract class BaseDatepickerComponent<P, D = Date> extends React.Compone
67
95
68
96
private getComponentStyle = ( style : StyleType ) : StyleType => {
69
97
const {
98
+ textMarginHorizontal,
99
+ textFontFamily,
70
100
textFontSize,
71
101
textLineHeight,
72
102
textFontWeight,
73
- textFontFamily,
74
103
textColor,
104
+ placeholderColor,
75
105
iconWidth,
76
106
iconHeight,
107
+ iconMarginHorizontal,
77
108
iconTintColor,
109
+ labelColor,
110
+ labelFontSize,
111
+ labelLineHeight,
112
+ labelMarginBottom,
113
+ labelFontWeight,
114
+ captionMarginTop,
115
+ captionColor,
116
+ captionFontSize,
117
+ captionLineHeight,
118
+ captionFontWeight,
119
+ captionIconWidth,
120
+ captionIconHeight,
121
+ captionIconMarginRight,
122
+ captionIconTintColor,
78
123
popoverWidth,
79
- ...containerStyles
124
+ ...controlParameters
80
125
} = style ;
81
126
82
127
return {
83
- control : containerStyles ,
84
- icon : {
85
- width : iconWidth ,
86
- height : iconHeight ,
87
- tintColor : iconTintColor ,
128
+ control : controlParameters ,
129
+ captionContainer : {
130
+ marginTop : captionMarginTop ,
88
131
} ,
89
132
text : {
133
+ marginHorizontal : textMarginHorizontal ,
134
+ fontFamily : textFontFamily ,
90
135
fontSize : textFontSize ,
91
- lineHeight : textLineHeight ,
92
136
fontWeight : textFontWeight ,
137
+ lineHeight : textLineHeight ,
93
138
color : textColor ,
94
- fontFamily : textFontFamily ,
139
+ } ,
140
+ placeholder : {
141
+ marginHorizontal : textMarginHorizontal ,
142
+ color : placeholderColor ,
143
+ } ,
144
+ icon : {
145
+ width : iconWidth ,
146
+ height : iconHeight ,
147
+ marginHorizontal : iconMarginHorizontal ,
148
+ tintColor : iconTintColor ,
149
+ } ,
150
+ label : {
151
+ color : labelColor ,
152
+ fontSize : labelFontSize ,
153
+ lineHeight : labelLineHeight ,
154
+ marginBottom : labelMarginBottom ,
155
+ fontWeight : labelFontWeight ,
156
+ } ,
157
+ captionIcon : {
158
+ width : captionIconWidth ,
159
+ height : captionIconHeight ,
160
+ tintColor : captionIconTintColor ,
161
+ marginRight : captionIconMarginRight ,
162
+ } ,
163
+ captionLabel : {
164
+ fontSize : captionFontSize ,
165
+ fontWeight : captionFontWeight ,
166
+ lineHeight : captionLineHeight ,
167
+ color : captionColor ,
95
168
} ,
96
169
popover : {
97
170
width : popoverWidth ,
171
+ marginBottom : captionMarginTop ,
98
172
} ,
99
173
} ;
100
174
} ;
101
175
102
176
private onPress = ( event : GestureResponderEvent ) : void => {
103
- this . setVisibility ( ) ;
177
+ this . toggleVisibility ( ) ;
104
178
105
179
if ( this . props . onPress ) {
106
180
this . props . onPress ( event ) ;
@@ -123,7 +197,7 @@ export abstract class BaseDatepickerComponent<P, D = Date> extends React.Compone
123
197
}
124
198
} ;
125
199
126
- private setVisibility = ( ) : void => {
200
+ private toggleVisibility = ( ) : void => {
127
201
const visible : boolean = ! this . state . visible ;
128
202
this . setState ( { visible } , this . dispatchActive ) ;
129
203
} ;
@@ -144,6 +218,35 @@ export abstract class BaseDatepickerComponent<P, D = Date> extends React.Compone
144
218
} ) ;
145
219
} ;
146
220
221
+ private renderLabelElement = ( style : TextStyle ) : TextElement => {
222
+ return (
223
+ < Text
224
+ key = { 1 }
225
+ style = { [ style , styles . label , this . props . labelStyle ] } >
226
+ { this . props . label }
227
+ </ Text >
228
+ ) ;
229
+ } ;
230
+
231
+ private renderCaptionElement = ( style : TextStyle ) : TextElement => {
232
+ return (
233
+ < Text
234
+ key = { 2 }
235
+ style = { [ style , styles . captionLabel , this . props . captionStyle ] } >
236
+ { this . props . caption }
237
+ </ Text >
238
+ ) ;
239
+ } ;
240
+
241
+ private renderCaptionIconElement = ( style : ImageStyle ) : IconElement => {
242
+ const iconElement : IconElement = this . props . captionIcon ( style ) ;
243
+
244
+ return React . cloneElement ( iconElement , {
245
+ key : 3 ,
246
+ style : [ style , iconElement . props . style ] ,
247
+ } ) ;
248
+ } ;
249
+
147
250
private renderTextElement = ( style : StyleType ) : TextElement => {
148
251
return (
149
252
< Text
@@ -180,42 +283,66 @@ export abstract class BaseDatepickerComponent<P, D = Date> extends React.Compone
180
283
) ;
181
284
} ;
182
285
183
- private renderComponentChildren = ( style : StyleType ) : DatepickerChildren < D > => {
286
+ private renderComponentChildren = ( style : StyleType ) : React . ReactElement [ ] => {
184
287
return [
185
288
this . renderCalendar ( ) ,
289
+ isValidString ( this . props . label ) && this . renderLabelElement ( style . label ) ,
186
290
this . renderControlElement ( style ) ,
291
+ isValidString ( this . props . caption ) && this . renderCaptionElement ( style . captionLabel ) ,
292
+ this . props . captionIcon && this . renderCaptionIconElement ( style . captionIcon ) ,
187
293
] ;
188
294
} ;
189
295
190
296
public render ( ) : React . ReactElement < ViewProps > {
191
- const { themedStyle, style } = this . props ;
297
+ const { themedStyle, style, placement } = this . props ;
192
298
const { popover, ...componentStyle } : StyleType = this . getComponentStyle ( themedStyle ) ;
193
299
194
- const [ calendarElement , controlElement ] = this . renderComponentChildren ( componentStyle ) ;
300
+ const [
301
+ calendarElement ,
302
+ labelElement ,
303
+ controlElement ,
304
+ captionElement ,
305
+ captionIconElement ,
306
+ ] = this . renderComponentChildren ( componentStyle ) ;
195
307
196
308
return (
197
309
< View style = { style } >
310
+ { labelElement }
198
311
< Popover
199
312
style = { [ popover , styles . popover ] }
200
- placement = { PopoverPlacements . BOTTOM_START }
313
+ placement = { placement }
201
314
visible = { this . state . visible }
202
315
content = { calendarElement }
203
- onBackdropPress = { this . setVisibility } >
316
+ onBackdropPress = { this . toggleVisibility } >
204
317
{ controlElement }
205
318
</ Popover >
319
+ < View style = { [ componentStyle . captionContainer , styles . captionContainer ] } >
320
+ { captionIconElement }
321
+ { captionElement }
322
+ </ View >
206
323
</ View >
207
324
) ;
208
325
}
209
326
}
210
327
211
328
const styles = StyleSheet . create ( {
329
+ popover : {
330
+ borderWidth : 0 ,
331
+ } ,
212
332
control : {
213
333
flexDirection : 'row' ,
214
334
alignItems : 'center' ,
215
335
justifyContent : 'space-between' ,
216
336
} ,
217
- popover : {
218
- borderWidth : 0 ,
337
+ label : {
338
+ textAlign : 'left' ,
339
+ } ,
340
+ captionContainer : {
341
+ flexDirection : 'row' ,
342
+ alignItems : 'center' ,
343
+ } ,
344
+ captionLabel : {
345
+ textAlign : 'left' ,
219
346
} ,
220
347
} ) ;
221
348
0 commit comments