@zendeskgarden/react-datepickers 8.75.0 → 8.76.0
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/dist/esm/elements/Datepicker/Datepicker.js +211 -0
- package/dist/esm/elements/Datepicker/components/Calendar.js +125 -0
- package/dist/esm/elements/Datepicker/components/MonthSelector.js +61 -0
- package/dist/esm/elements/Datepicker/utils/datepicker-reducer.js +187 -0
- package/dist/esm/elements/Datepicker/utils/garden-placements.js +56 -0
- package/dist/esm/elements/Datepicker/utils/useDatepickerContext.js +14 -0
- package/dist/esm/elements/DatepickerRange/DatepickerRange.js +101 -0
- package/dist/esm/elements/DatepickerRange/components/Calendar.js +42 -0
- package/dist/esm/elements/DatepickerRange/components/End.js +79 -0
- package/dist/esm/elements/DatepickerRange/components/Month.js +270 -0
- package/dist/esm/elements/DatepickerRange/components/Start.js +79 -0
- package/dist/esm/elements/DatepickerRange/utils/datepicker-range-reducer.js +319 -0
- package/dist/esm/elements/DatepickerRange/utils/useDatepickerRangeContext.js +14 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/node_modules/@zendeskgarden/svg-icons/src/16/chevron-left-stroke.svg.js +25 -0
- package/dist/esm/node_modules/@zendeskgarden/svg-icons/src/16/chevron-right-stroke.svg.js +25 -0
- package/dist/esm/styled/StyledCalendar.js +21 -0
- package/dist/esm/styled/StyledCalendarItem.js +34 -0
- package/dist/esm/styled/StyledDatepicker.js +32 -0
- package/dist/esm/styled/StyledDay.js +54 -0
- package/dist/esm/styled/StyledDayLabel.js +21 -0
- package/dist/esm/styled/StyledHeader.js +21 -0
- package/dist/esm/styled/StyledHeaderLabel.js +21 -0
- package/dist/esm/styled/StyledHeaderPaddle.js +38 -0
- package/dist/esm/styled/StyledHighlight.js +50 -0
- package/dist/esm/styled/StyledMenu.js +22 -0
- package/dist/esm/styled/StyledMenuWrapper.js +28 -0
- package/dist/esm/styled/StyledRangeCalendar.js +22 -0
- package/dist/esm/types/index.js +11 -0
- package/dist/esm/utils/calendar-utils.js +88 -0
- package/dist/index.cjs.js +12 -28
- package/package.json +5 -5
- package/dist/index.esm.js +0 -1714
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Zendesk, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed under the Apache License, Version 2.0
|
|
5
|
+
* found at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
*/
|
|
7
|
+
import React__default, { forwardRef, useContext, useCallback, useReducer, useRef, useEffect, useState, useMemo } from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { ThemeContext } from 'styled-components';
|
|
10
|
+
import { Manager, Reference, Popper } from 'react-popper';
|
|
11
|
+
import { composeEventHandlers, KEYS } from '@zendeskgarden/container-utilities';
|
|
12
|
+
import { WEEK_STARTS_ON, PLACEMENT } from '../../types/index.js';
|
|
13
|
+
import { getRtlPopperPlacement, getPopperPlacement } from './utils/garden-placements.js';
|
|
14
|
+
import { Calendar } from './components/Calendar.js';
|
|
15
|
+
import { datepickerReducer, retrieveInitialState } from './utils/datepicker-reducer.js';
|
|
16
|
+
import { DatepickerContext } from './utils/useDatepickerContext.js';
|
|
17
|
+
import { StyledMenu } from '../../styled/StyledMenu.js';
|
|
18
|
+
import { StyledMenuWrapper } from '../../styled/StyledMenuWrapper.js';
|
|
19
|
+
import '../../styled/StyledDatepicker.js';
|
|
20
|
+
import '../../styled/StyledRangeCalendar.js';
|
|
21
|
+
import '../../styled/StyledHeader.js';
|
|
22
|
+
import '../../styled/StyledHeaderPaddle.js';
|
|
23
|
+
import '../../styled/StyledHeaderLabel.js';
|
|
24
|
+
import '../../styled/StyledCalendar.js';
|
|
25
|
+
import '../../styled/StyledCalendarItem.js';
|
|
26
|
+
import '../../styled/StyledDayLabel.js';
|
|
27
|
+
import '../../styled/StyledHighlight.js';
|
|
28
|
+
import '../../styled/StyledDay.js';
|
|
29
|
+
|
|
30
|
+
const Datepicker = forwardRef((props, calendarRef) => {
|
|
31
|
+
const {
|
|
32
|
+
children,
|
|
33
|
+
placement,
|
|
34
|
+
popperModifiers,
|
|
35
|
+
eventsEnabled,
|
|
36
|
+
zIndex,
|
|
37
|
+
isAnimated,
|
|
38
|
+
refKey,
|
|
39
|
+
value,
|
|
40
|
+
isCompact,
|
|
41
|
+
onChange,
|
|
42
|
+
formatDate,
|
|
43
|
+
minValue,
|
|
44
|
+
maxValue,
|
|
45
|
+
locale,
|
|
46
|
+
weekStartsOn,
|
|
47
|
+
customParseDate,
|
|
48
|
+
...menuProps
|
|
49
|
+
} = props;
|
|
50
|
+
const theme = useContext(ThemeContext);
|
|
51
|
+
const memoizedReducer = useCallback(datepickerReducer({
|
|
52
|
+
value,
|
|
53
|
+
formatDate,
|
|
54
|
+
locale,
|
|
55
|
+
customParseDate,
|
|
56
|
+
onChange
|
|
57
|
+
}), [value, formatDate, locale, onChange, customParseDate]);
|
|
58
|
+
const [state, dispatch] = useReducer(memoizedReducer, retrieveInitialState(props));
|
|
59
|
+
const scheduleUpdateRef = useRef(undefined);
|
|
60
|
+
const inputRef = useRef(null);
|
|
61
|
+
const isInputMouseDownRef = useRef(false);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (state.isOpen && scheduleUpdateRef.current) {
|
|
64
|
+
scheduleUpdateRef.current();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const [isVisible, setIsVisible] = useState(state.isOpen);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
let timeout;
|
|
70
|
+
if (state.isOpen) {
|
|
71
|
+
setIsVisible(true);
|
|
72
|
+
} else if (isAnimated) {
|
|
73
|
+
timeout = setTimeout(() => setIsVisible(false), 200);
|
|
74
|
+
} else {
|
|
75
|
+
setIsVisible(false);
|
|
76
|
+
}
|
|
77
|
+
return () => clearTimeout(timeout);
|
|
78
|
+
}, [state.isOpen, isAnimated]);
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
dispatch({
|
|
81
|
+
type: 'CONTROLLED_VALUE_CHANGE',
|
|
82
|
+
value
|
|
83
|
+
});
|
|
84
|
+
}, [value]);
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
dispatch({
|
|
87
|
+
type: 'CONTROLLED_LOCALE_CHANGE'
|
|
88
|
+
});
|
|
89
|
+
}, [locale]);
|
|
90
|
+
const popperPlacement = theme.rtl ? getRtlPopperPlacement(placement) : getPopperPlacement(placement);
|
|
91
|
+
const contextValue = useMemo(() => ({
|
|
92
|
+
state,
|
|
93
|
+
dispatch
|
|
94
|
+
}), [state, dispatch]);
|
|
95
|
+
return React__default.createElement(DatepickerContext.Provider, {
|
|
96
|
+
value: contextValue
|
|
97
|
+
}, React__default.createElement(Manager, null, React__default.createElement(Reference, null, _ref => {
|
|
98
|
+
let {
|
|
99
|
+
ref
|
|
100
|
+
} = _ref;
|
|
101
|
+
const childElement = React__default.Children.only(children);
|
|
102
|
+
return React__default.cloneElement(childElement, {
|
|
103
|
+
[refKey]: refValue => {
|
|
104
|
+
ref(refValue);
|
|
105
|
+
inputRef.current = refValue;
|
|
106
|
+
},
|
|
107
|
+
onMouseDown: composeEventHandlers(childElement.props.onMouseDown, () => {
|
|
108
|
+
isInputMouseDownRef.current = true;
|
|
109
|
+
}),
|
|
110
|
+
onMouseUp: composeEventHandlers(childElement.props.onMouseUp, () => {
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
isInputMouseDownRef.current = false;
|
|
113
|
+
}, 0);
|
|
114
|
+
}),
|
|
115
|
+
onClick: composeEventHandlers(childElement.props.onClick, () => {
|
|
116
|
+
if (isInputMouseDownRef.current && !state.isOpen) {
|
|
117
|
+
dispatch({
|
|
118
|
+
type: 'OPEN'
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}),
|
|
122
|
+
onBlur: composeEventHandlers(childElement.props.onBlur, () => {
|
|
123
|
+
dispatch({
|
|
124
|
+
type: 'CLOSE'
|
|
125
|
+
});
|
|
126
|
+
}),
|
|
127
|
+
onChange: composeEventHandlers(childElement.props.onChange, e => {
|
|
128
|
+
dispatch({
|
|
129
|
+
type: 'MANUALLY_UPDATE_INPUT',
|
|
130
|
+
value: e.target.value
|
|
131
|
+
});
|
|
132
|
+
}),
|
|
133
|
+
onKeyDown: composeEventHandlers(childElement.props.onKeyDown, e => {
|
|
134
|
+
switch (e.key) {
|
|
135
|
+
case KEYS.ESCAPE:
|
|
136
|
+
case KEYS.ENTER:
|
|
137
|
+
dispatch({
|
|
138
|
+
type: 'CLOSE'
|
|
139
|
+
});
|
|
140
|
+
break;
|
|
141
|
+
case KEYS.UP:
|
|
142
|
+
case KEYS.DOWN:
|
|
143
|
+
case KEYS.SPACE:
|
|
144
|
+
dispatch({
|
|
145
|
+
type: 'OPEN'
|
|
146
|
+
});
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}),
|
|
150
|
+
autoComplete: 'off',
|
|
151
|
+
value: state.inputValue
|
|
152
|
+
});
|
|
153
|
+
}), React__default.createElement(Popper, {
|
|
154
|
+
placement: popperPlacement,
|
|
155
|
+
modifiers: popperModifiers
|
|
156
|
+
,
|
|
157
|
+
eventsEnabled: state.isOpen && eventsEnabled
|
|
158
|
+
}, _ref2 => {
|
|
159
|
+
let {
|
|
160
|
+
ref,
|
|
161
|
+
style,
|
|
162
|
+
scheduleUpdate,
|
|
163
|
+
placement: currentPlacement
|
|
164
|
+
} = _ref2;
|
|
165
|
+
scheduleUpdateRef.current = scheduleUpdate;
|
|
166
|
+
return React__default.createElement(StyledMenuWrapper, {
|
|
167
|
+
ref: ref,
|
|
168
|
+
style: style,
|
|
169
|
+
isHidden: !state.isOpen,
|
|
170
|
+
isAnimated: isAnimated && (state.isOpen || isVisible),
|
|
171
|
+
placement: currentPlacement,
|
|
172
|
+
zIndex: zIndex
|
|
173
|
+
}, (state.isOpen || isVisible) && React__default.createElement(StyledMenu, menuProps, React__default.createElement(Calendar, {
|
|
174
|
+
ref: calendarRef,
|
|
175
|
+
isCompact: isCompact,
|
|
176
|
+
value: value,
|
|
177
|
+
minValue: minValue,
|
|
178
|
+
maxValue: maxValue,
|
|
179
|
+
locale: locale,
|
|
180
|
+
weekStartsOn: weekStartsOn
|
|
181
|
+
})));
|
|
182
|
+
})));
|
|
183
|
+
});
|
|
184
|
+
Datepicker.displayName = 'Datepicker';
|
|
185
|
+
Datepicker.propTypes = {
|
|
186
|
+
value: PropTypes.any,
|
|
187
|
+
onChange: PropTypes.any,
|
|
188
|
+
formatDate: PropTypes.func,
|
|
189
|
+
locale: PropTypes.any,
|
|
190
|
+
weekStartsOn: PropTypes.oneOf(WEEK_STARTS_ON),
|
|
191
|
+
minValue: PropTypes.any,
|
|
192
|
+
maxValue: PropTypes.any,
|
|
193
|
+
isCompact: PropTypes.bool,
|
|
194
|
+
customParseDate: PropTypes.any,
|
|
195
|
+
refKey: PropTypes.string,
|
|
196
|
+
placement: PropTypes.oneOf(PLACEMENT),
|
|
197
|
+
popperModifiers: PropTypes.any,
|
|
198
|
+
isAnimated: PropTypes.bool,
|
|
199
|
+
eventsEnabled: PropTypes.bool,
|
|
200
|
+
zIndex: PropTypes.number
|
|
201
|
+
};
|
|
202
|
+
Datepicker.defaultProps = {
|
|
203
|
+
placement: 'bottom-start',
|
|
204
|
+
refKey: 'ref',
|
|
205
|
+
isAnimated: true,
|
|
206
|
+
eventsEnabled: true,
|
|
207
|
+
zIndex: 1000,
|
|
208
|
+
locale: 'en-US'
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export { Datepicker };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Zendesk, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed under the Apache License, Version 2.0
|
|
5
|
+
* found at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
*/
|
|
7
|
+
import React__default, { forwardRef, useCallback } from 'react';
|
|
8
|
+
import { startOfMonth } from 'date-fns/startOfMonth';
|
|
9
|
+
import { endOfMonth } from 'date-fns/endOfMonth';
|
|
10
|
+
import { startOfWeek } from 'date-fns/startOfWeek';
|
|
11
|
+
import { endOfWeek } from 'date-fns/endOfWeek';
|
|
12
|
+
import { eachDayOfInterval } from 'date-fns/eachDayOfInterval';
|
|
13
|
+
import { addDays } from 'date-fns/addDays';
|
|
14
|
+
import { isToday } from 'date-fns/isToday';
|
|
15
|
+
import { isSameDay } from 'date-fns/isSameDay';
|
|
16
|
+
import { isSameMonth } from 'date-fns/isSameMonth';
|
|
17
|
+
import { isBefore } from 'date-fns/isBefore';
|
|
18
|
+
import { isAfter } from 'date-fns/isAfter';
|
|
19
|
+
import { getDate } from 'date-fns/getDate';
|
|
20
|
+
import '../../../styled/StyledMenu.js';
|
|
21
|
+
import '../../../styled/StyledMenuWrapper.js';
|
|
22
|
+
import { StyledDatepicker } from '../../../styled/StyledDatepicker.js';
|
|
23
|
+
import '../../../styled/StyledRangeCalendar.js';
|
|
24
|
+
import '../../../styled/StyledHeader.js';
|
|
25
|
+
import '../../../styled/StyledHeaderPaddle.js';
|
|
26
|
+
import '../../../styled/StyledHeaderLabel.js';
|
|
27
|
+
import { StyledCalendar } from '../../../styled/StyledCalendar.js';
|
|
28
|
+
import { StyledCalendarItem } from '../../../styled/StyledCalendarItem.js';
|
|
29
|
+
import { StyledDayLabel } from '../../../styled/StyledDayLabel.js';
|
|
30
|
+
import '../../../styled/StyledHighlight.js';
|
|
31
|
+
import { StyledDay } from '../../../styled/StyledDay.js';
|
|
32
|
+
import useDatepickerContext from '../utils/useDatepickerContext.js';
|
|
33
|
+
import { getStartOfWeek } from '../../../utils/calendar-utils.js';
|
|
34
|
+
import { MonthSelector } from './MonthSelector.js';
|
|
35
|
+
|
|
36
|
+
const Calendar = forwardRef((_ref, ref) => {
|
|
37
|
+
let {
|
|
38
|
+
value,
|
|
39
|
+
minValue,
|
|
40
|
+
maxValue,
|
|
41
|
+
isCompact,
|
|
42
|
+
locale,
|
|
43
|
+
weekStartsOn
|
|
44
|
+
} = _ref;
|
|
45
|
+
const {
|
|
46
|
+
state,
|
|
47
|
+
dispatch
|
|
48
|
+
} = useDatepickerContext();
|
|
49
|
+
const preferredWeekStartsOn = weekStartsOn || getStartOfWeek(locale);
|
|
50
|
+
const monthStartDate = startOfMonth(state.previewDate);
|
|
51
|
+
const monthEndDate = endOfMonth(monthStartDate);
|
|
52
|
+
const startDate = startOfWeek(monthStartDate, {
|
|
53
|
+
weekStartsOn: preferredWeekStartsOn
|
|
54
|
+
});
|
|
55
|
+
const endDate = endOfWeek(monthEndDate, {
|
|
56
|
+
weekStartsOn: preferredWeekStartsOn
|
|
57
|
+
});
|
|
58
|
+
const dayLabelFormatter = useCallback(date => {
|
|
59
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
|
60
|
+
weekday: 'short'
|
|
61
|
+
});
|
|
62
|
+
return formatter.format(date);
|
|
63
|
+
}, [locale]);
|
|
64
|
+
const dayLabels = eachDayOfInterval({
|
|
65
|
+
start: startDate,
|
|
66
|
+
end: addDays(startDate, 6)
|
|
67
|
+
}).map(date => {
|
|
68
|
+
const formattedDayLabel = dayLabelFormatter(date);
|
|
69
|
+
return React__default.createElement(StyledCalendarItem, {
|
|
70
|
+
key: `day-label-${formattedDayLabel}`,
|
|
71
|
+
isCompact: isCompact
|
|
72
|
+
}, React__default.createElement(StyledDayLabel, {
|
|
73
|
+
isCompact: isCompact
|
|
74
|
+
}, formattedDayLabel));
|
|
75
|
+
});
|
|
76
|
+
const items = eachDayOfInterval({
|
|
77
|
+
start: startDate,
|
|
78
|
+
end: endDate
|
|
79
|
+
}).map((date, itemsIndex) => {
|
|
80
|
+
const formattedDayLabel = getDate(date);
|
|
81
|
+
const isCurrentDate = isToday(date);
|
|
82
|
+
const isPreviousMonth = !isSameMonth(date, state.previewDate);
|
|
83
|
+
const isSelected = value && isSameDay(date, value);
|
|
84
|
+
let isDisabled = false;
|
|
85
|
+
if (minValue !== undefined) {
|
|
86
|
+
isDisabled = isBefore(date, minValue) && !isSameDay(date, minValue);
|
|
87
|
+
}
|
|
88
|
+
if (maxValue !== undefined) {
|
|
89
|
+
isDisabled = isDisabled || isAfter(date, maxValue) && !isSameDay(date, maxValue);
|
|
90
|
+
}
|
|
91
|
+
return React__default.createElement(StyledCalendarItem, {
|
|
92
|
+
key: `day-${itemsIndex}`,
|
|
93
|
+
isCompact: isCompact
|
|
94
|
+
}, React__default.createElement(StyledDay, {
|
|
95
|
+
isToday: isCurrentDate,
|
|
96
|
+
isPreviousMonth: isPreviousMonth,
|
|
97
|
+
isSelected: isSelected,
|
|
98
|
+
isDisabled: isDisabled,
|
|
99
|
+
isCompact: isCompact,
|
|
100
|
+
onClick: () => {
|
|
101
|
+
if (!isDisabled) {
|
|
102
|
+
dispatch({
|
|
103
|
+
type: 'SELECT_DATE',
|
|
104
|
+
value: date
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}, formattedDayLabel));
|
|
109
|
+
});
|
|
110
|
+
return React__default.createElement(StyledDatepicker, {
|
|
111
|
+
ref: ref,
|
|
112
|
+
isCompact: isCompact,
|
|
113
|
+
onMouseDown: e => {
|
|
114
|
+
e.preventDefault();
|
|
115
|
+
}
|
|
116
|
+
}, React__default.createElement(MonthSelector, {
|
|
117
|
+
locale: locale,
|
|
118
|
+
isCompact: isCompact
|
|
119
|
+
}), React__default.createElement(StyledCalendar, {
|
|
120
|
+
isCompact: isCompact
|
|
121
|
+
}, dayLabels, items));
|
|
122
|
+
});
|
|
123
|
+
Calendar.displayName = 'Calendar';
|
|
124
|
+
|
|
125
|
+
export { Calendar };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Zendesk, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed under the Apache License, Version 2.0
|
|
5
|
+
* found at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
*/
|
|
7
|
+
import React__default, { useCallback } from 'react';
|
|
8
|
+
import '../../../styled/StyledMenu.js';
|
|
9
|
+
import '../../../styled/StyledMenuWrapper.js';
|
|
10
|
+
import '../../../styled/StyledDatepicker.js';
|
|
11
|
+
import '../../../styled/StyledRangeCalendar.js';
|
|
12
|
+
import { StyledHeader } from '../../../styled/StyledHeader.js';
|
|
13
|
+
import { StyledHeaderPaddle } from '../../../styled/StyledHeaderPaddle.js';
|
|
14
|
+
import { StyledHeaderLabel } from '../../../styled/StyledHeaderLabel.js';
|
|
15
|
+
import '../../../styled/StyledCalendar.js';
|
|
16
|
+
import '../../../styled/StyledCalendarItem.js';
|
|
17
|
+
import '../../../styled/StyledDayLabel.js';
|
|
18
|
+
import '../../../styled/StyledHighlight.js';
|
|
19
|
+
import '../../../styled/StyledDay.js';
|
|
20
|
+
import useDatepickerContext from '../utils/useDatepickerContext.js';
|
|
21
|
+
import SvgChevronLeftStroke from '../../../node_modules/@zendeskgarden/svg-icons/src/16/chevron-left-stroke.svg.js';
|
|
22
|
+
import SvgChevronRightStroke from '../../../node_modules/@zendeskgarden/svg-icons/src/16/chevron-right-stroke.svg.js';
|
|
23
|
+
|
|
24
|
+
const MonthSelector = _ref => {
|
|
25
|
+
let {
|
|
26
|
+
locale,
|
|
27
|
+
isCompact
|
|
28
|
+
} = _ref;
|
|
29
|
+
const {
|
|
30
|
+
state,
|
|
31
|
+
dispatch
|
|
32
|
+
} = useDatepickerContext();
|
|
33
|
+
const headerLabelFormatter = useCallback(date => {
|
|
34
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
|
35
|
+
month: 'long',
|
|
36
|
+
year: 'numeric'
|
|
37
|
+
});
|
|
38
|
+
return formatter.format(date);
|
|
39
|
+
}, [locale]);
|
|
40
|
+
return React__default.createElement(StyledHeader, {
|
|
41
|
+
isCompact: isCompact
|
|
42
|
+
}, React__default.createElement(StyledHeaderPaddle, {
|
|
43
|
+
isCompact: isCompact,
|
|
44
|
+
onClick: () => {
|
|
45
|
+
dispatch({
|
|
46
|
+
type: 'PREVIEW_PREVIOUS_MONTH'
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}, React__default.createElement(SvgChevronLeftStroke, null)), React__default.createElement(StyledHeaderLabel, {
|
|
50
|
+
isCompact: isCompact
|
|
51
|
+
}, headerLabelFormatter(state.previewDate)), React__default.createElement(StyledHeaderPaddle, {
|
|
52
|
+
isCompact: isCompact,
|
|
53
|
+
onClick: () => {
|
|
54
|
+
dispatch({
|
|
55
|
+
type: 'PREVIEW_NEXT_MONTH'
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}, React__default.createElement(SvgChevronRightStroke, null)));
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export { MonthSelector };
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Zendesk, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed under the Apache License, Version 2.0
|
|
5
|
+
* found at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
*/
|
|
7
|
+
import { addMonths } from 'date-fns/addMonths';
|
|
8
|
+
import { subMonths } from 'date-fns/subMonths';
|
|
9
|
+
import { isValid } from 'date-fns/isValid';
|
|
10
|
+
import { parse } from 'date-fns/parse';
|
|
11
|
+
import { isBefore } from 'date-fns/isBefore';
|
|
12
|
+
import { isSameDay } from 'date-fns/isSameDay';
|
|
13
|
+
|
|
14
|
+
function parseInputValue(_ref) {
|
|
15
|
+
let {
|
|
16
|
+
inputValue,
|
|
17
|
+
customParseDate
|
|
18
|
+
} = _ref;
|
|
19
|
+
if (customParseDate) {
|
|
20
|
+
return customParseDate(inputValue);
|
|
21
|
+
}
|
|
22
|
+
const MINIMUM_DATE = new Date(1001, 0, 0);
|
|
23
|
+
let tryParseDate = parse(inputValue, 'P', new Date());
|
|
24
|
+
if (isValid(tryParseDate) && !isBefore(tryParseDate, MINIMUM_DATE)) {
|
|
25
|
+
return tryParseDate;
|
|
26
|
+
}
|
|
27
|
+
tryParseDate = parse(inputValue, 'PP', new Date());
|
|
28
|
+
if (isValid(tryParseDate) && !isBefore(tryParseDate, MINIMUM_DATE)) {
|
|
29
|
+
return tryParseDate;
|
|
30
|
+
}
|
|
31
|
+
tryParseDate = parse(inputValue, 'PPP', new Date());
|
|
32
|
+
if (isValid(tryParseDate) && !isBefore(tryParseDate, MINIMUM_DATE)) {
|
|
33
|
+
return tryParseDate;
|
|
34
|
+
}
|
|
35
|
+
return new Date(NaN);
|
|
36
|
+
}
|
|
37
|
+
function formatInputValue(_ref2) {
|
|
38
|
+
let {
|
|
39
|
+
date,
|
|
40
|
+
locale,
|
|
41
|
+
formatDate
|
|
42
|
+
} = _ref2;
|
|
43
|
+
if (!date) {
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
46
|
+
if (formatDate) {
|
|
47
|
+
return formatDate(date);
|
|
48
|
+
}
|
|
49
|
+
return new Intl.DateTimeFormat(locale, {
|
|
50
|
+
month: 'long',
|
|
51
|
+
day: 'numeric',
|
|
52
|
+
year: 'numeric'
|
|
53
|
+
}).format(date);
|
|
54
|
+
}
|
|
55
|
+
const datepickerReducer = _ref3 => {
|
|
56
|
+
let {
|
|
57
|
+
value,
|
|
58
|
+
formatDate,
|
|
59
|
+
locale,
|
|
60
|
+
customParseDate,
|
|
61
|
+
onChange
|
|
62
|
+
} = _ref3;
|
|
63
|
+
return (state, action) => {
|
|
64
|
+
switch (action.type) {
|
|
65
|
+
case 'OPEN':
|
|
66
|
+
return {
|
|
67
|
+
...state,
|
|
68
|
+
isOpen: true,
|
|
69
|
+
previewDate: value || new Date()
|
|
70
|
+
};
|
|
71
|
+
case 'CLOSE':
|
|
72
|
+
{
|
|
73
|
+
const inputValue = formatInputValue({
|
|
74
|
+
date: value,
|
|
75
|
+
locale,
|
|
76
|
+
formatDate
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
...state,
|
|
80
|
+
isOpen: false,
|
|
81
|
+
inputValue
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
case 'PREVIEW_NEXT_MONTH':
|
|
85
|
+
{
|
|
86
|
+
const previewDate = addMonths(state.previewDate, 1);
|
|
87
|
+
return {
|
|
88
|
+
...state,
|
|
89
|
+
previewDate
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
case 'PREVIEW_PREVIOUS_MONTH':
|
|
93
|
+
{
|
|
94
|
+
const previewDate = subMonths(state.previewDate, 1);
|
|
95
|
+
return {
|
|
96
|
+
...state,
|
|
97
|
+
previewDate
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
case 'MANUALLY_UPDATE_INPUT':
|
|
101
|
+
{
|
|
102
|
+
const inputValue = action.value;
|
|
103
|
+
const currentDate = parseInputValue({
|
|
104
|
+
inputValue,
|
|
105
|
+
customParseDate
|
|
106
|
+
});
|
|
107
|
+
if (onChange && currentDate && isValid(currentDate) && !isSameDay(value, currentDate)) {
|
|
108
|
+
onChange(currentDate);
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
...state,
|
|
112
|
+
isOpen: true,
|
|
113
|
+
inputValue
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
case 'CONTROLLED_VALUE_CHANGE':
|
|
117
|
+
{
|
|
118
|
+
const previewDate = action.value || new Date();
|
|
119
|
+
const inputValue = formatInputValue({
|
|
120
|
+
date: action.value,
|
|
121
|
+
locale,
|
|
122
|
+
formatDate
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
...state,
|
|
126
|
+
previewDate,
|
|
127
|
+
inputValue
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
case 'CONTROLLED_LOCALE_CHANGE':
|
|
131
|
+
{
|
|
132
|
+
const inputValue = formatInputValue({
|
|
133
|
+
date: value,
|
|
134
|
+
locale,
|
|
135
|
+
formatDate
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
...state,
|
|
139
|
+
inputValue
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
case 'SELECT_DATE':
|
|
143
|
+
{
|
|
144
|
+
const inputValue = formatInputValue({
|
|
145
|
+
date: action.value,
|
|
146
|
+
locale,
|
|
147
|
+
formatDate
|
|
148
|
+
});
|
|
149
|
+
if (onChange && action.value && isValid(action.value) && !isSameDay(value, action.value)) {
|
|
150
|
+
onChange(action.value);
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
...state,
|
|
154
|
+
isOpen: false,
|
|
155
|
+
inputValue
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
default:
|
|
159
|
+
throw new Error();
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
function retrieveInitialState(initialProps) {
|
|
164
|
+
let previewDate = initialProps.value;
|
|
165
|
+
if (previewDate === undefined || !isValid(previewDate)) {
|
|
166
|
+
previewDate = new Date();
|
|
167
|
+
}
|
|
168
|
+
let inputValue = '';
|
|
169
|
+
if (initialProps.value !== undefined) {
|
|
170
|
+
if (initialProps.formatDate) {
|
|
171
|
+
inputValue = initialProps.formatDate(initialProps.value);
|
|
172
|
+
} else {
|
|
173
|
+
inputValue = new Intl.DateTimeFormat(initialProps.locale, {
|
|
174
|
+
month: 'long',
|
|
175
|
+
day: 'numeric',
|
|
176
|
+
year: 'numeric'
|
|
177
|
+
}).format(previewDate);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
isOpen: false,
|
|
182
|
+
previewDate,
|
|
183
|
+
inputValue
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { datepickerReducer, retrieveInitialState };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Zendesk, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed under the Apache License, Version 2.0
|
|
5
|
+
* found at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
*/
|
|
7
|
+
function getPopperPlacement(gardenPlacement) {
|
|
8
|
+
switch (gardenPlacement) {
|
|
9
|
+
case 'end':
|
|
10
|
+
return 'right';
|
|
11
|
+
case 'end-top':
|
|
12
|
+
return 'right-start';
|
|
13
|
+
case 'end-bottom':
|
|
14
|
+
return 'right-end';
|
|
15
|
+
case 'start':
|
|
16
|
+
return 'left';
|
|
17
|
+
case 'start-top':
|
|
18
|
+
return 'left-start';
|
|
19
|
+
case 'start-bottom':
|
|
20
|
+
return 'left-end';
|
|
21
|
+
default:
|
|
22
|
+
return gardenPlacement;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function getRtlPopperPlacement(gardenPlacement) {
|
|
26
|
+
const popperPlacement = getPopperPlacement(gardenPlacement);
|
|
27
|
+
switch (popperPlacement) {
|
|
28
|
+
case 'left':
|
|
29
|
+
return 'right';
|
|
30
|
+
case 'left-start':
|
|
31
|
+
return 'right-start';
|
|
32
|
+
case 'left-end':
|
|
33
|
+
return 'right-end';
|
|
34
|
+
case 'top-start':
|
|
35
|
+
return 'top-end';
|
|
36
|
+
case 'top-end':
|
|
37
|
+
return 'top-start';
|
|
38
|
+
case 'right':
|
|
39
|
+
return 'left';
|
|
40
|
+
case 'right-start':
|
|
41
|
+
return 'left-start';
|
|
42
|
+
case 'right-end':
|
|
43
|
+
return 'left-end';
|
|
44
|
+
case 'bottom-start':
|
|
45
|
+
return 'bottom-end';
|
|
46
|
+
case 'bottom-end':
|
|
47
|
+
return 'bottom-start';
|
|
48
|
+
default:
|
|
49
|
+
return popperPlacement;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function getMenuPosition(popperPlacement) {
|
|
53
|
+
return popperPlacement ? popperPlacement.split('-')[0] : 'bottom';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { getMenuPosition, getPopperPlacement, getRtlPopperPlacement };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Zendesk, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Use of this source code is governed under the Apache License, Version 2.0
|
|
5
|
+
* found at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
*/
|
|
7
|
+
import { createContext, useContext } from 'react';
|
|
8
|
+
|
|
9
|
+
const DatepickerContext = createContext(undefined);
|
|
10
|
+
const useDatepickerContext = () => {
|
|
11
|
+
return useContext(DatepickerContext);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export { DatepickerContext, useDatepickerContext as default };
|