bright-components 10.1.0 → 10.2.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.
@@ -53,15 +53,17 @@ const Checkmark = _styledComponents.default.span`
53
53
  position: relative;
54
54
  top: ${_ref3 => {
55
55
  let {
56
- outline
56
+ outline,
57
+ disabled
57
58
  } = _ref3;
58
- return outline ? '-4px' : '-2px';
59
+ return outline && !disabled ? '-4px' : '-2px';
59
60
  }};
60
61
  left: ${_ref4 => {
61
62
  let {
62
- outline
63
+ outline,
64
+ disabled
63
65
  } = _ref4;
64
- return outline ? '-2px' : '0';
66
+ return outline && !disabled ? '-2px' : '0';
65
67
  }};
66
68
  display: block;
67
69
  width: 16px;
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+
6
+ var _react = _interopRequireWildcard(require("react"));
7
+
8
+ var _dateFns = require("date-fns");
9
+
10
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
11
+
12
+ var _Input = _interopRequireDefault(require("../../Input"));
13
+
14
+ var _ErrorMessage = _interopRequireDefault(require("../../ErrorMessage"));
15
+
16
+ var _propTypes = require("prop-types");
17
+
18
+ var _colors = _interopRequireDefault(require("../../../constants/colors"));
19
+
20
+ var _spacing = _interopRequireDefault(require("../../../constants/spacing"));
21
+
22
+ var _Calendar = _interopRequireDefault(require("../../Icons/Calendar"));
23
+
24
+ var _reactGa = require("react-ga");
25
+
26
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
+
28
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
29
+
30
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
31
+
32
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
33
+
34
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
35
+
36
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
37
+
38
+ const HiddenBox = (0, _styledComponents.default)(_Input.default.withComponent('div'))`
39
+ display: flex;
40
+ align-items: center;
41
+ ${props => props.error && `
42
+ margin-bottom: 0px !important;
43
+ border-bottom-left-radius: 0px;
44
+ border-bottom-right-radius: 0px;
45
+ border-color: ${_colors.default.borderError} !important;
46
+ `};
47
+ input {
48
+ height: 2.5rem !important;
49
+ min-height: 2.5rem !important;
50
+ border: 0 !important;
51
+ margin: 0 !important;
52
+ padding: 0 !important;
53
+ box-shadow: none !important;
54
+ }
55
+ `;
56
+ HiddenBox.displayName = 'HiddenBox';
57
+ const OpenCalendarIcon = (0, _styledComponents.default)(_Calendar.default)`
58
+ cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
59
+ margin-left: ${_spacing.default.s1};
60
+ color: ${_colors.default.primary};
61
+ `;
62
+ OpenCalendarIcon.displayName = 'OpenCalendarIcon';
63
+ const formats = {
64
+ CA: {
65
+ placeholderDate: 'YY/MM/DD',
66
+ dateFormat: 'yy/MM/dd'
67
+ },
68
+ default: {
69
+ placeholderDate: 'DD/MM/YY',
70
+ dateFormat: 'dd/MM/yy'
71
+ }
72
+ };
73
+
74
+ const makeInnerDate = (date, dateFormat) => {
75
+ if (date.from) {
76
+ return (0, _dateFns.format)(date.from, dateFormat);
77
+ }
78
+
79
+ return '';
80
+ };
81
+
82
+ const NewDisplay = _ref => {
83
+ let {
84
+ placeholder,
85
+ datesToDisplay,
86
+ range,
87
+ allowClear,
88
+ yearRange,
89
+ onSelectedDate,
90
+ locale,
91
+ clearValue,
92
+ disabled,
93
+ error,
94
+ toggleDayPicker,
95
+ GA: {
96
+ category,
97
+ actionId
98
+ },
99
+ recordValue,
100
+ dayPickerOpen
101
+ } = _ref;
102
+ const {
103
+ placeholderDate,
104
+ dateFormat
105
+ } = formats[locale] || formats.default;
106
+ const [hasFocus, setHasFocus] = (0, _react.useState)(false);
107
+ const [hasError, setHasError] = (0, _react.useState)(false);
108
+ const [innerDate, setInnerDate] = (0, _react.useState)(makeInnerDate(range, dateFormat));
109
+ return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement(HiddenBox, {
110
+ error: error,
111
+ "data-testid": "input-selector"
112
+ }, _react.default.createElement(_Input.default, {
113
+ "data-testid": "new input",
114
+ placeholder: hasFocus ? placeholderDate : placeholder,
115
+ value: hasFocus ? innerDate : datesToDisplay,
116
+ fullWidth: true,
117
+ disabled: disabled,
118
+ onFocus: () => {
119
+ setInnerDate(makeInnerDate(range, dateFormat));
120
+ setHasFocus(true);
121
+ setHasError(false);
122
+ },
123
+ onBlur: _ref2 => {
124
+ let {
125
+ target: {
126
+ value
127
+ }
128
+ } = _ref2;
129
+ setHasFocus(false);
130
+ if (dayPickerOpen) toggleDayPicker();
131
+
132
+ if (!value && (allowClear || !range.from)) {
133
+ return range.from ? clearValue() : null;
134
+ }
135
+
136
+ const newDate = {
137
+ from: (0, _dateFns.parse)(value, dateFormat, new Date()),
138
+ to: (0, _dateFns.parse)(value, dateFormat, new Date())
139
+ };
140
+ const fromYear = (0, _dateFns.getYear)(newDate.from);
141
+ const toYear = (0, _dateFns.getYear)(newDate.to);
142
+
143
+ if (!(0, _dateFns.isValid)(newDate.from) || !(0, _dateFns.isValid)(newDate.to) || fromYear < yearRange.min || toYear > yearRange.max) {
144
+ setHasError(!((0, _dateFns.isValid)(newDate.from) && (0, _dateFns.isValid)(newDate.to)) ? 'invalid' : 'range');
145
+ return range.from ? onSelectedDate(allowClear ? '' : range) : null;
146
+ }
147
+
148
+ if (category) {
149
+ const label = `${(0, _dateFns.format)(newDate.from, 'EEE dd MMM')} ${(0, _dateFns.format)(newDate.from, 'yyyy')}`;
150
+ (0, _reactGa.event)(_objectSpread({
151
+ category,
152
+ action: `${actionId} - Set via Typing`
153
+ }, recordValue ? {
154
+ label
155
+ } : {}));
156
+ }
157
+
158
+ return onSelectedDate(newDate);
159
+ },
160
+ onChange: _ref3 => {
161
+ let {
162
+ target: {
163
+ value
164
+ }
165
+ } = _ref3;
166
+ setInnerDate(value.replace(/.*\/$/g, text => value.length < innerDate.length ? value.slice(0, -1) : text).replace(/(\d\d)(\d)/g, '$1/$2').replace(/^(\d\/)$/g, '0$1').replace(/\d\d$/g, text => value.length > innerDate.length && value.length < 7 ? `${text}/` : text).replace(/^(\d\d\/)(\d\/)$/g, '$10$2').replace(/[^\d/]/g, '').replace(/^(.{0,8})(.*)$/g, '$1').replace(/\/\/$/g, '/'));
167
+ }
168
+ }), _react.default.createElement(OpenCalendarIcon, {
169
+ "data-testid": "calendarIcon",
170
+ size: 22,
171
+ disabled: disabled,
172
+ onClick: () => {
173
+ setHasError(false);
174
+ toggleDayPicker();
175
+ }
176
+ })), hasError && _react.default.createElement(_ErrorMessage.default, {
177
+ showIcon: false
178
+ }, hasError === 'invalid' ? 'Date is invalid' : `Year is outside of range. Must be between ${yearRange.min} - ${yearRange.max}`));
179
+ };
180
+
181
+ NewDisplay.propTypes = {
182
+ placeholder: _propTypes.string.isRequired,
183
+ datesToDisplay: _propTypes.string.isRequired,
184
+ range: (0, _propTypes.shape)({
185
+ from: (0, _propTypes.instanceOf)(Date),
186
+ to: (0, _propTypes.instanceOf)(Date)
187
+ }).isRequired,
188
+ allowClear: _propTypes.bool.isRequired,
189
+ yearRange: (0, _propTypes.shape)({
190
+ min: _propTypes.number,
191
+ max: _propTypes.number
192
+ }).isRequired,
193
+ onSelectedDate: _propTypes.func.isRequired,
194
+ locale: _propTypes.string.isRequired,
195
+ clearValue: _propTypes.func.isRequired,
196
+ disabled: _propTypes.bool.isRequired,
197
+ error: _propTypes.bool.isRequired,
198
+ toggleDayPicker: _propTypes.func.isRequired,
199
+ GA: (0, _propTypes.shape)({
200
+ category: _propTypes.string,
201
+ actionId: _propTypes.string
202
+ }).isRequired,
203
+ recordValue: _propTypes.bool.isRequired,
204
+ dayPickerOpen: _propTypes.bool.isRequired
205
+ };
206
+ var _default = NewDisplay;
207
+ exports.default = _default;
@@ -33,6 +33,8 @@ var _breakpoints = _interopRequireDefault(require("../../constants/breakpoints")
33
33
 
34
34
  var _Calendar = _interopRequireDefault(require("../Icons/Calendar"));
35
35
 
36
+ var _NewDayPicker = _interopRequireDefault(require("./NewDayPicker"));
37
+
36
38
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
37
39
 
38
40
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -271,15 +273,17 @@ class DayPicker extends _react.default.Component {
271
273
  closeButton,
272
274
  panelAbsoluteOnDesktop,
273
275
  onSelectedDate,
274
- isDateSelect
276
+ isDateSelect,
277
+ typeable
275
278
  } = _this$props,
276
- rest = _objectWithoutProperties(_this$props, ["allowClear", "placeholder", "dateRange", "yearRange", "yearsToDisplay", "style", "error", "disabled", "shortcuts", "disabledDays", "GA", "recordValue", "legacyInputStyle", "closeButton", "panelAbsoluteOnDesktop", "onSelectedDate", "isDateSelect"]);
279
+ rest = _objectWithoutProperties(_this$props, ["allowClear", "placeholder", "dateRange", "yearRange", "yearsToDisplay", "style", "error", "disabled", "shortcuts", "disabledDays", "GA", "recordValue", "legacyInputStyle", "closeButton", "panelAbsoluteOnDesktop", "onSelectedDate", "isDateSelect", "typeable"]);
277
280
 
278
281
  const {
279
282
  dayPickerOpen
280
283
  } = this.state;
281
284
  const {
282
- range
285
+ range,
286
+ locale
283
287
  } = this.props;
284
288
  const fromDate = range.from ? (0, _dateFns.format)(range.from, this.getDisplayFormat()) : '';
285
289
  const toDate = range.to ? (0, _dateFns.format)(range.to, friendlyShortWithYear) : '';
@@ -290,7 +294,7 @@ class DayPicker extends _react.default.Component {
290
294
  } = style,
291
295
  otherStyles = _objectWithoutProperties(style, ["width"]);
292
296
 
293
- return _react.default.createElement(DayPickerInputContainer, rest, _react.default.createElement(InputBox, {
297
+ return _react.default.createElement(DayPickerInputContainer, rest, !typeable || dateRange ? _react.default.createElement(InputBox, {
294
298
  onClick: this.toggleDayPicker,
295
299
  error: error,
296
300
  disabled: disabled,
@@ -299,7 +303,22 @@ class DayPicker extends _react.default.Component {
299
303
  }, datesToDisplay ? _react.default.createElement("span", null, datesToDisplay) : _react.default.createElement(Placeholder, null, placeholder), _react.default.createElement(OpenCalendarIcon, {
300
304
  size: 22,
301
305
  disabled: disabled
302
- })), dayPickerOpen && _react.default.createElement(DayRangeContainer, {
306
+ })) : _react.default.createElement(_NewDayPicker.default, {
307
+ placeholder: placeholder,
308
+ datesToDisplay: datesToDisplay,
309
+ range: range,
310
+ allowClear: allowClear,
311
+ yearRange: yearRange,
312
+ onSelectedDate: onSelectedDate,
313
+ locale: locale,
314
+ clearValue: this.clearValue,
315
+ disabled: disabled,
316
+ error: error,
317
+ toggleDayPicker: this.toggleDayPicker,
318
+ GA: GA,
319
+ recordValue: recordValue,
320
+ dayPickerOpen: dayPickerOpen
321
+ }), dayPickerOpen && _react.default.createElement(DayRangeContainer, {
303
322
  panelAbsoluteOnDesktop: panelAbsoluteOnDesktop,
304
323
  style: otherStyles,
305
324
  width: width,
@@ -360,7 +379,9 @@ DayPicker.propTypes = {
360
379
  legacyInputStyle: _propTypes.bool,
361
380
  closeButton: _propTypes.bool,
362
381
  panelAbsoluteOnDesktop: _propTypes.bool,
363
- isDateSelect: _propTypes.bool
382
+ isDateSelect: _propTypes.bool,
383
+ typeable: _propTypes.bool,
384
+ locale: _propTypes.string
364
385
  };
365
386
  DayPicker.defaultProps = {
366
387
  recordValue: false,
@@ -385,7 +406,9 @@ DayPicker.defaultProps = {
385
406
  legacyInputStyle: false,
386
407
  closeButton: false,
387
408
  panelAbsoluteOnDesktop: true,
388
- isDateSelect: false
409
+ isDateSelect: false,
410
+ typeable: false,
411
+ locale: 'GB'
389
412
  };
390
413
 
391
414
  var _default = (0, _reactOnclickoutside.default)(DayPicker);
@@ -207,7 +207,7 @@ class DayPickerPanel extends _react.default.Component {
207
207
  to
208
208
  }
209
209
  } = this.state;
210
- const actionEvent = selectedDay ? 'Set' : 'Apply';
210
+ const actionEvent = selectedDay ? 'Set via Date Picker' : 'Apply';
211
211
 
212
212
  if (category) {
213
213
  const label = dateRange ? `${(0, _dateFns.format)(from, friendlyShort)} - ${(0, _dateFns.format)(to || from, friendlyShort)} ${(0, _dateFns.format)(to || from, 'yyyy')}` : `${(0, _dateFns.format)(from, friendlyShort)} ${(0, _dateFns.format)(from, 'yyyy')}`;
@@ -11,6 +11,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
11
11
 
12
12
  const ModalBody = _styledComponents.default.div`
13
13
  padding: ${props => props.noPadding ? '0px' : _spacing.default.s2};
14
+ overflow-y: auto;
14
15
  `;
15
16
  ModalBody.displayName = 'ModalBody';
16
17
  /* @component */
@@ -55,6 +55,8 @@ const Background = _styledComponents.default.div`
55
55
  align-items: center;
56
56
  `;
57
57
  const ModalContainer = _styledComponents.default.div`
58
+ display: flex;
59
+ flex-direction: column;
58
60
  background: white;
59
61
  position: relative;
60
62
  width: ${props => props.width};
@@ -64,7 +66,6 @@ const ModalContainer = _styledComponents.default.div`
64
66
  border-radius: ${_vars.default.borderRadius};
65
67
  max-height: 90%;
66
68
  overflow-x: hidden;
67
- overflow-y: auto;
68
69
  ${props => props.version === '1' && '-webkit-overflow-scrolling: touch'};
69
70
 
70
71
  ${props => props.allowOverflow && (0, _styledComponents.css)`
@@ -133,6 +133,7 @@ const TimePicker = _ref => {
133
133
  const valueAsString = (0, _durationToTimeString.default)(value);
134
134
  return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement(MobileTimePicker, {
135
135
  type: "time",
136
+ "data-testid": "mobileTimePicker",
136
137
  onChange: e => {
137
138
  const timeString = e.target.value;
138
139
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  var _enzyme = require("enzyme");
4
4
 
5
+ var _react = require("@testing-library/react");
6
+
5
7
  var _enzymeAdapterReact = _interopRequireDefault(require("enzyme-adapter-react-16"));
6
8
 
7
9
  var _reactGa = _interopRequireDefault(require("react-ga"));
@@ -53,4 +55,7 @@ afterEach(() => {
53
55
  });
54
56
  (0, _enzyme.configure)({
55
57
  adapter: new _enzymeAdapterReact.default()
58
+ });
59
+ (0, _react.configure)({
60
+ defaultHidden: true
56
61
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bright-components",
3
- "version": "10.1.0",
3
+ "version": "10.2.1",
4
4
  "private": false,
5
5
  "main": "./dist",
6
6
  "repository": {
@@ -73,10 +73,11 @@
73
73
  "@babel/preset-env": "^7.16.5",
74
74
  "@babel/preset-react": "^7.7.4",
75
75
  "@svgr/webpack": "4.3.2",
76
+ "@testing-library/dom": "^8.11.2",
76
77
  "@testing-library/jest-dom": "^4.1.0",
77
78
  "@testing-library/react": "^9.1.4",
78
79
  "@testing-library/react-hooks": "^2.0.1",
79
- "@testing-library/user-event": "^7.0.1",
80
+ "@testing-library/user-event": "^12.8.3",
80
81
  "babel-eslint": "10.0.2",
81
82
  "babel-jest": "^24.9.0",
82
83
  "babel-loader": "8.0.6",
@@ -27,8 +27,8 @@ Box.displayName = 'Box';
27
27
 
28
28
  const Checkmark = styled.span`
29
29
  position: relative;
30
- top: ${({ outline }) => (outline ? '-4px' : '-2px')};
31
- left: ${({ outline }) => (outline ? '-2px' : '0')};
30
+ top: ${({ outline, disabled }) => (outline && !disabled ? '-4px' : '-2px')};
31
+ left: ${({ outline, disabled }) => (outline && !disabled ? '-2px' : '0')};
32
32
  display: block;
33
33
  width: 16px;
34
34
  height: 16px;
@@ -0,0 +1,208 @@
1
+ import React, { useState } from 'react';
2
+ import { format, isValid, parse, getYear } from 'date-fns';
3
+ import styled from 'styled-components';
4
+ import Input from 'components/Input';
5
+ import ErrorMessage from 'components/ErrorMessage';
6
+ import { string, func, bool, shape, instanceOf, number } from 'prop-types';
7
+ import colors from 'constants/colors';
8
+ import spacing from 'constants/spacing';
9
+ import CalendarIcon from 'components/Icons/Calendar/';
10
+ import { event } from 'react-ga';
11
+
12
+ const HiddenBox = styled(Input.withComponent('div'))`
13
+ display: flex;
14
+ align-items: center;
15
+ ${props =>
16
+ props.error &&
17
+ `
18
+ margin-bottom: 0px !important;
19
+ border-bottom-left-radius: 0px;
20
+ border-bottom-right-radius: 0px;
21
+ border-color: ${colors.borderError} !important;
22
+ `};
23
+ input {
24
+ height: 2.5rem !important;
25
+ min-height: 2.5rem !important;
26
+ border: 0 !important;
27
+ margin: 0 !important;
28
+ padding: 0 !important;
29
+ box-shadow: none !important;
30
+ }
31
+ `;
32
+ HiddenBox.displayName = 'HiddenBox';
33
+
34
+ const OpenCalendarIcon = styled(CalendarIcon)`
35
+ cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')};
36
+ margin-left: ${spacing.s1};
37
+ color: ${colors.primary};
38
+ `;
39
+ OpenCalendarIcon.displayName = 'OpenCalendarIcon';
40
+
41
+ const formats = {
42
+ CA: { placeholderDate: 'YY/MM/DD', dateFormat: 'yy/MM/dd' },
43
+ default: { placeholderDate: 'DD/MM/YY', dateFormat: 'dd/MM/yy' }
44
+ };
45
+
46
+ const makeInnerDate = (date, dateFormat) => {
47
+ if (date.from) {
48
+ return format(date.from, dateFormat);
49
+ }
50
+ return '';
51
+ };
52
+
53
+ const NewDisplay = ({
54
+ placeholder,
55
+ datesToDisplay,
56
+ range,
57
+ allowClear,
58
+ yearRange,
59
+ onSelectedDate,
60
+ locale,
61
+ clearValue,
62
+ disabled,
63
+ error,
64
+ toggleDayPicker,
65
+ GA: { category, actionId },
66
+ recordValue,
67
+ dayPickerOpen
68
+ }) => {
69
+ const { placeholderDate, dateFormat } = formats[locale] || formats.default;
70
+
71
+ const [hasFocus, setHasFocus] = useState(false);
72
+ const [hasError, setHasError] = useState(false);
73
+ const [innerDate, setInnerDate] = useState(
74
+ makeInnerDate(range, dateFormat)
75
+ );
76
+
77
+ return (
78
+ <>
79
+ <HiddenBox error={error} data-testid="input-selector">
80
+ <Input
81
+ data-testid="new input"
82
+ placeholder={hasFocus ? placeholderDate : placeholder}
83
+ value={hasFocus ? innerDate : datesToDisplay}
84
+ fullWidth
85
+ disabled={disabled}
86
+ onFocus={() => {
87
+ setInnerDate(makeInnerDate(range, dateFormat));
88
+ setHasFocus(true);
89
+ setHasError(false);
90
+ }}
91
+ onBlur={({ target: { value } }) => {
92
+ setHasFocus(false);
93
+ if (dayPickerOpen) toggleDayPicker();
94
+ if (!value && (allowClear || !range.from)) {
95
+ return range.from ? clearValue() : null;
96
+ }
97
+
98
+ const newDate = {
99
+ from: parse(value, dateFormat, new Date()),
100
+ to: parse(value, dateFormat, new Date())
101
+ };
102
+
103
+ const fromYear = getYear(newDate.from);
104
+ const toYear = getYear(newDate.to);
105
+
106
+ if (
107
+ !isValid(newDate.from) ||
108
+ !isValid(newDate.to) ||
109
+ fromYear < yearRange.min ||
110
+ toYear > yearRange.max
111
+ ) {
112
+ setHasError(
113
+ !(isValid(newDate.from) && isValid(newDate.to))
114
+ ? 'invalid'
115
+ : 'range'
116
+ );
117
+
118
+ return range.from
119
+ ? onSelectedDate(allowClear ? '' : range)
120
+ : null;
121
+ }
122
+
123
+ if (category) {
124
+ const label = `${format(
125
+ newDate.from,
126
+ 'EEE dd MMM'
127
+ )} ${format(newDate.from, 'yyyy')}`;
128
+
129
+ event({
130
+ category,
131
+ action: `${actionId} - Set via Typing`,
132
+ ...(recordValue ? { label } : {})
133
+ });
134
+ }
135
+
136
+ return onSelectedDate(newDate);
137
+ }}
138
+ onChange={({ target: { value } }) => {
139
+ setInnerDate(
140
+ value
141
+ .replace(/.*\/$/g, text =>
142
+ value.length < innerDate.length
143
+ ? value.slice(0, -1)
144
+ : text
145
+ )
146
+ .replace(/(\d\d)(\d)/g, '$1/$2')
147
+ .replace(/^(\d\/)$/g, '0$1')
148
+ .replace(/\d\d$/g, text =>
149
+ value.length > innerDate.length &&
150
+ value.length < 7
151
+ ? `${text}/`
152
+ : text
153
+ )
154
+ .replace(/^(\d\d\/)(\d\/)$/g, '$10$2')
155
+ .replace(/[^\d/]/g, '')
156
+ .replace(/^(.{0,8})(.*)$/g, '$1')
157
+ .replace(/\/\/$/g, '/')
158
+ );
159
+ }}
160
+ />
161
+ <OpenCalendarIcon
162
+ data-testid="calendarIcon"
163
+ size={22}
164
+ disabled={disabled}
165
+ onClick={() => {
166
+ setHasError(false);
167
+ toggleDayPicker();
168
+ }}
169
+ />
170
+ </HiddenBox>
171
+ {hasError && (
172
+ <ErrorMessage showIcon={false}>
173
+ {hasError === 'invalid'
174
+ ? 'Date is invalid'
175
+ : `Year is outside of range. Must be between ${yearRange.min} - ${yearRange.max}`}
176
+ </ErrorMessage>
177
+ )}
178
+ </>
179
+ );
180
+ };
181
+
182
+ NewDisplay.propTypes = {
183
+ placeholder: string.isRequired,
184
+ datesToDisplay: string.isRequired,
185
+ range: shape({
186
+ from: instanceOf(Date),
187
+ to: instanceOf(Date)
188
+ }).isRequired,
189
+ allowClear: bool.isRequired,
190
+ yearRange: shape({
191
+ min: number,
192
+ max: number
193
+ }).isRequired,
194
+ onSelectedDate: func.isRequired,
195
+ locale: string.isRequired,
196
+ clearValue: func.isRequired,
197
+ disabled: bool.isRequired,
198
+ error: bool.isRequired,
199
+ toggleDayPicker: func.isRequired,
200
+ GA: shape({
201
+ category: string,
202
+ actionId: string
203
+ }).isRequired,
204
+ recordValue: bool.isRequired,
205
+ dayPickerOpen: bool.isRequired
206
+ };
207
+
208
+ export default NewDisplay;
@@ -231,3 +231,20 @@ initialState={dates: {from: new Date(2018, 3, 1), to: undefined}};
231
231
  isDateSelect={true}
232
232
  />
233
233
  ```
234
+ Day Picker - typeable
235
+ ```js
236
+ initialState={dates: {from: new Date(2018, 3, 1), to: undefined}};
237
+ <DayPicker
238
+ range={state.dates}
239
+ yearRange={{ min: 2000, max: 2030}}
240
+ style={{
241
+ width: '70%'
242
+ }}
243
+ GA={{
244
+ category: 'Test',
245
+ actionId: 'Test'
246
+ }}
247
+ onSelectedDate={dates=>setState({dates})}
248
+ typeable
249
+ />
250
+ ```