1 | import React from 'react';
|
2 | import PropTypes from 'prop-types';
|
3 | import { forbidExtraProps, nonNegativeInteger } from 'airbnb-prop-types';
|
4 | import { withStyles, withStylesPropTypes } from 'react-with-styles';
|
5 |
|
6 | import { SingleDatePickerInputPhrases } from '../defaultPhrases';
|
7 | import getPhrasePropTypes from '../utils/getPhrasePropTypes';
|
8 | import noflip from '../utils/noflip';
|
9 |
|
10 | import DateInput from './DateInput';
|
11 | import IconPositionShape from '../shapes/IconPositionShape';
|
12 |
|
13 | import CloseButton from './CloseButton';
|
14 | import CalendarIcon from './CalendarIcon';
|
15 |
|
16 | import openDirectionShape from '../shapes/OpenDirectionShape';
|
17 | import { ICON_BEFORE_POSITION, ICON_AFTER_POSITION, OPEN_DOWN } from '../constants';
|
18 |
|
19 | const propTypes = forbidExtraProps({
|
20 | ...withStylesPropTypes,
|
21 | id: PropTypes.string.isRequired,
|
22 | children: PropTypes.node,
|
23 | placeholder: PropTypes.string,
|
24 | ariaLabel: PropTypes.string,
|
25 | displayValue: PropTypes.string,
|
26 | screenReaderMessage: PropTypes.string,
|
27 | focused: PropTypes.bool,
|
28 | isFocused: PropTypes.bool,
|
29 | disabled: PropTypes.bool,
|
30 | required: PropTypes.bool,
|
31 | readOnly: PropTypes.bool,
|
32 | openDirection: openDirectionShape,
|
33 | showCaret: PropTypes.bool,
|
34 | showClearDate: PropTypes.bool,
|
35 | customCloseIcon: PropTypes.node,
|
36 | showDefaultInputIcon: PropTypes.bool,
|
37 | inputIconPosition: IconPositionShape,
|
38 | customInputIcon: PropTypes.node,
|
39 | isRTL: PropTypes.bool,
|
40 | noBorder: PropTypes.bool,
|
41 | block: PropTypes.bool,
|
42 | small: PropTypes.bool,
|
43 | regular: PropTypes.bool,
|
44 | verticalSpacing: nonNegativeInteger,
|
45 |
|
46 | onChange: PropTypes.func,
|
47 | onClearDate: PropTypes.func,
|
48 | onFocus: PropTypes.func,
|
49 | onKeyDownShiftTab: PropTypes.func,
|
50 | onKeyDownTab: PropTypes.func,
|
51 | onKeyDownArrowDown: PropTypes.func,
|
52 | onKeyDownQuestionMark: PropTypes.func,
|
53 |
|
54 |
|
55 | phrases: PropTypes.shape(getPhrasePropTypes(SingleDatePickerInputPhrases)),
|
56 | });
|
57 |
|
58 | const defaultProps = {
|
59 | children: null,
|
60 | placeholder: 'Select Date',
|
61 | ariaLabel: undefined,
|
62 | displayValue: '',
|
63 | screenReaderMessage: '',
|
64 | focused: false,
|
65 | isFocused: false,
|
66 | disabled: false,
|
67 | required: false,
|
68 | readOnly: false,
|
69 | openDirection: OPEN_DOWN,
|
70 | showCaret: false,
|
71 | showClearDate: false,
|
72 | showDefaultInputIcon: false,
|
73 | inputIconPosition: ICON_BEFORE_POSITION,
|
74 | customCloseIcon: null,
|
75 | customInputIcon: null,
|
76 | isRTL: false,
|
77 | noBorder: false,
|
78 | block: false,
|
79 | small: false,
|
80 | regular: false,
|
81 | verticalSpacing: undefined,
|
82 |
|
83 | onChange() {},
|
84 | onClearDate() {},
|
85 | onFocus() {},
|
86 | onKeyDownShiftTab() {},
|
87 | onKeyDownTab() {},
|
88 | onKeyDownArrowDown() {},
|
89 | onKeyDownQuestionMark() {},
|
90 |
|
91 |
|
92 | phrases: SingleDatePickerInputPhrases,
|
93 | };
|
94 |
|
95 | function SingleDatePickerInput({
|
96 | id,
|
97 | children,
|
98 | css,
|
99 | placeholder,
|
100 | ariaLabel,
|
101 | displayValue,
|
102 | focused,
|
103 | isFocused,
|
104 | disabled,
|
105 | required,
|
106 | readOnly,
|
107 | showCaret,
|
108 | showClearDate,
|
109 | showDefaultInputIcon,
|
110 | inputIconPosition,
|
111 | phrases,
|
112 | onClearDate,
|
113 | onChange,
|
114 | onFocus,
|
115 | onKeyDownShiftTab,
|
116 | onKeyDownTab,
|
117 | onKeyDownArrowDown,
|
118 | onKeyDownQuestionMark,
|
119 | screenReaderMessage,
|
120 | customCloseIcon,
|
121 | customInputIcon,
|
122 | openDirection,
|
123 | isRTL,
|
124 | noBorder,
|
125 | block,
|
126 | small,
|
127 | regular,
|
128 | verticalSpacing,
|
129 | styles,
|
130 | }) {
|
131 | const calendarIcon = customInputIcon || (
|
132 | <CalendarIcon {...css(styles.SingleDatePickerInput_calendarIcon_svg)} />
|
133 | );
|
134 | const closeIcon = customCloseIcon || (
|
135 | <CloseButton
|
136 | {...css(
|
137 | styles.SingleDatePickerInput_clearDate_svg,
|
138 | small && styles.SingleDatePickerInput_clearDate_svg__small,
|
139 | )}
|
140 | />
|
141 | );
|
142 |
|
143 | const screenReaderText = screenReaderMessage || phrases.keyboardForwardNavigationInstructions;
|
144 | const inputIcon = (showDefaultInputIcon || customInputIcon !== null) && (
|
145 | <button
|
146 | {...css(styles.SingleDatePickerInput_calendarIcon)}
|
147 | type="button"
|
148 | disabled={disabled}
|
149 | aria-label={phrases.focusStartDate}
|
150 | onClick={onFocus}
|
151 | >
|
152 | {calendarIcon}
|
153 | </button>
|
154 | );
|
155 |
|
156 | return (
|
157 | <div
|
158 | {...css(
|
159 | styles.SingleDatePickerInput,
|
160 | disabled && styles.SingleDatePickerInput__disabled,
|
161 | isRTL && styles.SingleDatePickerInput__rtl,
|
162 | !noBorder && styles.SingleDatePickerInput__withBorder,
|
163 | block && styles.SingleDatePickerInput__block,
|
164 | showClearDate && styles.SingleDatePickerInput__showClearDate,
|
165 | )}
|
166 | >
|
167 | {inputIconPosition === ICON_BEFORE_POSITION && inputIcon}
|
168 |
|
169 | <DateInput
|
170 | id={id}
|
171 | placeholder={placeholder}
|
172 | ariaLabel={ariaLabel}
|
173 | displayValue={displayValue}
|
174 | screenReaderMessage={screenReaderText}
|
175 | focused={focused}
|
176 | isFocused={isFocused}
|
177 | disabled={disabled}
|
178 | required={required}
|
179 | readOnly={readOnly}
|
180 | showCaret={showCaret}
|
181 | onChange={onChange}
|
182 | onFocus={onFocus}
|
183 | onKeyDownShiftTab={onKeyDownShiftTab}
|
184 | onKeyDownTab={onKeyDownTab}
|
185 | onKeyDownArrowDown={onKeyDownArrowDown}
|
186 | onKeyDownQuestionMark={onKeyDownQuestionMark}
|
187 | openDirection={openDirection}
|
188 | verticalSpacing={verticalSpacing}
|
189 | small={small}
|
190 | regular={regular}
|
191 | block={block}
|
192 | />
|
193 |
|
194 | {children}
|
195 |
|
196 | {showClearDate && (
|
197 | <button
|
198 | {...css(
|
199 | styles.SingleDatePickerInput_clearDate,
|
200 | small && styles.SingleDatePickerInput_clearDate__small,
|
201 | !customCloseIcon && styles.SingleDatePickerInput_clearDate__default,
|
202 | !displayValue && styles.SingleDatePickerInput_clearDate__hide,
|
203 | )}
|
204 | type="button"
|
205 | aria-label={phrases.clearDate}
|
206 | disabled={disabled}
|
207 | onClick={onClearDate}
|
208 | >
|
209 | {closeIcon}
|
210 | </button>
|
211 | )}
|
212 |
|
213 | {inputIconPosition === ICON_AFTER_POSITION && inputIcon}
|
214 |
|
215 | </div>
|
216 | );
|
217 | }
|
218 |
|
219 | SingleDatePickerInput.propTypes = propTypes;
|
220 | SingleDatePickerInput.defaultProps = defaultProps;
|
221 |
|
222 | export default withStyles(({ reactDates: { border, color } }) => ({
|
223 | SingleDatePickerInput: {
|
224 | display: 'inline-block',
|
225 | backgroundColor: color.background,
|
226 | },
|
227 |
|
228 | SingleDatePickerInput__withBorder: {
|
229 | borderColor: color.border,
|
230 | borderWidth: border.pickerInput.borderWidth,
|
231 | borderStyle: border.pickerInput.borderStyle,
|
232 | borderRadius: border.pickerInput.borderRadius,
|
233 | },
|
234 |
|
235 | SingleDatePickerInput__rtl: {
|
236 | direction: noflip('rtl'),
|
237 | },
|
238 |
|
239 | SingleDatePickerInput__disabled: {
|
240 | backgroundColor: color.disabled,
|
241 | },
|
242 |
|
243 | SingleDatePickerInput__block: {
|
244 | display: 'block',
|
245 | },
|
246 |
|
247 | SingleDatePickerInput__showClearDate: {
|
248 | paddingRight: 30,
|
249 | },
|
250 |
|
251 | SingleDatePickerInput_clearDate: {
|
252 | background: 'none',
|
253 | border: 0,
|
254 | color: 'inherit',
|
255 | font: 'inherit',
|
256 | lineHeight: 'normal',
|
257 | overflow: 'visible',
|
258 |
|
259 | cursor: 'pointer',
|
260 | padding: 10,
|
261 | margin: '0 10px 0 5px',
|
262 | position: 'absolute',
|
263 | right: 0,
|
264 | top: '50%',
|
265 | transform: 'translateY(-50%)',
|
266 | },
|
267 |
|
268 | SingleDatePickerInput_clearDate__default: {
|
269 | ':focus': {
|
270 | background: color.core.border,
|
271 | borderRadius: '50%',
|
272 | },
|
273 |
|
274 | ':hover': {
|
275 | background: color.core.border,
|
276 | borderRadius: '50%',
|
277 | },
|
278 | },
|
279 |
|
280 | SingleDatePickerInput_clearDate__small: {
|
281 | padding: 6,
|
282 | },
|
283 |
|
284 | SingleDatePickerInput_clearDate__hide: {
|
285 | visibility: 'hidden',
|
286 | },
|
287 |
|
288 | SingleDatePickerInput_clearDate_svg: {
|
289 | fill: color.core.grayLight,
|
290 | height: 12,
|
291 | width: 15,
|
292 | verticalAlign: 'middle',
|
293 | },
|
294 |
|
295 | SingleDatePickerInput_clearDate_svg__small: {
|
296 | height: 9,
|
297 | },
|
298 |
|
299 | SingleDatePickerInput_calendarIcon: {
|
300 | background: 'none',
|
301 | border: 0,
|
302 | color: 'inherit',
|
303 | font: 'inherit',
|
304 | lineHeight: 'normal',
|
305 | overflow: 'visible',
|
306 |
|
307 | cursor: 'pointer',
|
308 | display: 'inline-block',
|
309 | verticalAlign: 'middle',
|
310 | padding: 10,
|
311 | margin: '0 5px 0 10px',
|
312 | },
|
313 |
|
314 | SingleDatePickerInput_calendarIcon_svg: {
|
315 | fill: color.core.grayLight,
|
316 | height: 15,
|
317 | width: 14,
|
318 | verticalAlign: 'middle',
|
319 | },
|
320 | }), { pureComponent: typeof React.PureComponent !== 'undefined' })(SingleDatePickerInput);
|