@primer/components 0.0.0-202192422618 → 0.0.0-202192522854
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/CHANGELOG.md +1 -1
- package/lib/DatePicker/DatePicker.js +10 -2
- package/lib/DatePicker/DatePickerAnchor.d.ts +1 -1
- package/lib/DatePicker/DatePickerAnchor.js +57 -8
- package/lib/DatePicker/DatePickerPanel.js +47 -11
- package/lib/DatePicker/Day.js +1 -1
- package/lib/DatePicker/Month.js +16 -6
- package/lib/DatePicker/useDatePicker.d.ts +10 -0
- package/lib/DatePicker/useDatePicker.js +22 -4
- package/lib-esm/DatePicker/DatePicker.js +10 -2
- package/lib-esm/DatePicker/DatePickerAnchor.d.ts +1 -1
- package/lib-esm/DatePicker/DatePickerAnchor.js +56 -8
- package/lib-esm/DatePicker/DatePickerPanel.js +46 -10
- package/lib-esm/DatePicker/Day.js +1 -1
- package/lib-esm/DatePicker/Month.js +15 -6
- package/lib-esm/DatePicker/useDatePicker.d.ts +10 -0
- package/lib-esm/DatePicker/useDatePicker.js +23 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -21,8 +21,11 @@ const DatePicker = ({
|
|
21
21
|
anchorVariant,
|
22
22
|
anchorRef: externalAnchorRef,
|
23
23
|
confirmation,
|
24
|
+
dateFormat,
|
24
25
|
focusTrapSettings,
|
25
26
|
focusZoneSettings,
|
27
|
+
maxDate,
|
28
|
+
minDate,
|
26
29
|
onOpen: onOpenExternal,
|
27
30
|
onClose: onCloseExternal,
|
28
31
|
open,
|
@@ -30,15 +33,20 @@ const DatePicker = ({
|
|
30
33
|
renderAnchor,
|
31
34
|
selection,
|
32
35
|
value,
|
33
|
-
view
|
36
|
+
view,
|
37
|
+
weekStartsOn
|
34
38
|
}) => {
|
35
39
|
const buttonRef = (0, _react.useRef)(null);
|
36
40
|
const [isOpen, setIsOpen] = (0, _react.useState)(false);
|
37
41
|
const datePickerConfiguration = {
|
38
42
|
anchorVariant,
|
39
43
|
confirmation,
|
44
|
+
dateFormat,
|
45
|
+
maxDate,
|
46
|
+
minDate,
|
40
47
|
selection,
|
41
|
-
view
|
48
|
+
view,
|
49
|
+
weekStartsOn
|
42
50
|
};
|
43
51
|
|
44
52
|
const onOpen = gesture => {
|
@@ -2,4 +2,4 @@ import React from 'react';
|
|
2
2
|
export interface DatePickerAnchorProps {
|
3
3
|
onAction?: (event?: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>) => void;
|
4
4
|
}
|
5
|
-
export declare const DatePickerAnchor: React.ForwardRefExoticComponent<DatePickerAnchorProps & React.RefAttributes<
|
5
|
+
export declare const DatePickerAnchor: React.ForwardRefExoticComponent<DatePickerAnchorProps & React.RefAttributes<HTMLDivElement>>;
|
@@ -11,7 +11,7 @@ var _styledComponents = _interopRequireDefault(require("styled-components"));
|
|
11
11
|
|
12
12
|
var _react = _interopRequireWildcard(require("react"));
|
13
13
|
|
14
|
-
var _Button =
|
14
|
+
var _Button = _interopRequireWildcard(require("../Button"));
|
15
15
|
|
16
16
|
var _Text = _interopRequireDefault(require("../Text"));
|
17
17
|
|
@@ -23,6 +23,8 @@ var _useDatePicker = _interopRequireDefault(require("./useDatePicker"));
|
|
23
23
|
|
24
24
|
var _TextInput = _interopRequireDefault(require("../TextInput"));
|
25
25
|
|
26
|
+
var _Box = _interopRequireDefault(require("../Box"));
|
27
|
+
|
26
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); }
|
27
29
|
|
28
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; }
|
@@ -39,7 +41,8 @@ const DatePickerAnchor = /*#__PURE__*/_react.default.forwardRef(({
|
|
39
41
|
}, ref) => {
|
40
42
|
const {
|
41
43
|
configuration: {
|
42
|
-
anchorVariant
|
44
|
+
anchorVariant,
|
45
|
+
iconPlacement
|
43
46
|
},
|
44
47
|
disabled,
|
45
48
|
formattedDate
|
@@ -60,15 +63,61 @@ const DatePickerAnchor = /*#__PURE__*/_react.default.forwardRef(({
|
|
60
63
|
|
61
64
|
onAction === null || onAction === void 0 ? void 0 : onAction(event);
|
62
65
|
}, [disabled, onAction]);
|
66
|
+
const onKeyPressHandler = (0, _react.useCallback)(e => {
|
67
|
+
console.log(e.currentTarget.value);
|
68
|
+
}, []);
|
69
|
+
const onInputChangeHandler = (0, _react.useCallback)(e => {
|
70
|
+
console.log(e.currentTarget.value);
|
71
|
+
}, []);
|
63
72
|
|
64
73
|
if (anchorVariant === 'input') {
|
65
|
-
|
66
|
-
|
67
|
-
|
74
|
+
const calendarButton = side => /*#__PURE__*/_react.default.createElement(_Button.ButtonInvisible, {
|
75
|
+
onClick: clickHandler,
|
76
|
+
sx: {
|
77
|
+
width: '32px',
|
78
|
+
px: '6px',
|
79
|
+
position: 'absolute',
|
80
|
+
[side]: '1px',
|
81
|
+
top: '1px'
|
82
|
+
}
|
83
|
+
}, /*#__PURE__*/_react.default.createElement(_StyledOcticon.default, {
|
84
|
+
icon: _octiconsReact.CalendarIcon
|
85
|
+
}));
|
86
|
+
|
87
|
+
const inputSx = () => {
|
88
|
+
if (iconPlacement === 'start') {
|
89
|
+
return {
|
90
|
+
pl: 5,
|
91
|
+
pr: 2
|
92
|
+
};
|
93
|
+
} else if (iconPlacement === 'end') {
|
94
|
+
return {
|
95
|
+
pl: 2,
|
96
|
+
pr: 5
|
97
|
+
};
|
98
|
+
} else {
|
99
|
+
return {};
|
100
|
+
}
|
101
|
+
};
|
102
|
+
|
103
|
+
return /*#__PURE__*/_react.default.createElement(_Box.default, {
|
104
|
+
ref: ref,
|
105
|
+
sx: {
|
106
|
+
position: 'relative',
|
107
|
+
display: 'flex',
|
108
|
+
flex: 1
|
109
|
+
}
|
110
|
+
}, iconPlacement === 'start' && calendarButton('left'), /*#__PURE__*/_react.default.createElement(_TextInput.default, {
|
111
|
+
defaultValue: formattedDate,
|
112
|
+
onKeyPress: onKeyPressHandler,
|
113
|
+
onChange: onInputChangeHandler,
|
114
|
+
sx: inputSx()
|
115
|
+
}), iconPlacement === 'end' && calendarButton('right'));
|
68
116
|
}
|
69
117
|
|
70
|
-
return /*#__PURE__*/_react.default.createElement(
|
71
|
-
ref: ref
|
118
|
+
return /*#__PURE__*/_react.default.createElement(_Box.default, {
|
119
|
+
ref: ref
|
120
|
+
}, /*#__PURE__*/_react.default.createElement(DatePickerAnchorButton, {
|
72
121
|
onClick: clickHandler,
|
73
122
|
onKeyPress: keyPressHandler
|
74
123
|
}, /*#__PURE__*/_react.default.createElement(_StyledOcticon.default, {
|
@@ -82,7 +131,7 @@ const DatePickerAnchor = /*#__PURE__*/_react.default.forwardRef(({
|
|
82
131
|
overflow: 'hidden',
|
83
132
|
textOverflow: 'ellipsis'
|
84
133
|
}
|
85
|
-
}, formattedDate));
|
134
|
+
}, formattedDate)));
|
86
135
|
});
|
87
136
|
|
88
137
|
exports.DatePickerAnchor = DatePickerAnchor;
|
@@ -7,7 +7,7 @@ exports.DatePickerPanel = void 0;
|
|
7
7
|
|
8
8
|
var _dateFns = require("date-fns");
|
9
9
|
|
10
|
-
var _react =
|
10
|
+
var _react = _interopRequireWildcard(require("react"));
|
11
11
|
|
12
12
|
var _Box = _interopRequireDefault(require("../Box"));
|
13
13
|
|
@@ -25,12 +25,12 @@ var _StyledOcticon = _interopRequireDefault(require("../StyledOcticon"));
|
|
25
25
|
|
26
26
|
var _Button = _interopRequireWildcard(require("../Button"));
|
27
27
|
|
28
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
29
|
+
|
28
30
|
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
31
|
|
30
32
|
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
33
|
|
32
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
33
|
-
|
34
34
|
const DatePickerPanelContainer = (0, _styledComponents.default)(_Box.default).withConfig({
|
35
35
|
displayName: "DatePickerPanel__DatePickerPanelContainer",
|
36
36
|
componentId: "sc-19upxpo-0"
|
@@ -52,23 +52,58 @@ const DatePickerPanel = () => {
|
|
52
52
|
const {
|
53
53
|
configuration,
|
54
54
|
saveValue,
|
55
|
-
revertValue
|
55
|
+
revertValue,
|
56
|
+
currentViewingDate,
|
57
|
+
goToMonth,
|
58
|
+
nextMonth,
|
59
|
+
previousMonth
|
56
60
|
} = (0, _useDatePicker.default)();
|
61
|
+
const previousDisabled = (0, _react.useMemo)(() => {
|
62
|
+
const {
|
63
|
+
minDate
|
64
|
+
} = configuration;
|
65
|
+
if (!minDate) return false;
|
66
|
+
const previous = (0, _dateFns.subMonths)(currentViewingDate, 1);
|
67
|
+
|
68
|
+
if (minDate.getFullYear() >= previous.getFullYear() && minDate.getMonth() > previous.getMonth()) {
|
69
|
+
return true;
|
70
|
+
}
|
71
|
+
|
72
|
+
return false;
|
73
|
+
}, [configuration, currentViewingDate]);
|
74
|
+
const nextDisabled = (0, _react.useMemo)(() => {
|
75
|
+
const {
|
76
|
+
maxDate,
|
77
|
+
view
|
78
|
+
} = configuration;
|
79
|
+
if (!maxDate) return false;
|
80
|
+
const next = (0, _dateFns.addMonths)(currentViewingDate, view === '2-month' ? 2 : 1);
|
81
|
+
|
82
|
+
if (maxDate.getFullYear() <= next.getFullYear() && maxDate.getMonth() < next.getMonth()) {
|
83
|
+
return true;
|
84
|
+
}
|
85
|
+
|
86
|
+
return false;
|
87
|
+
}, [configuration, currentViewingDate]);
|
57
88
|
return /*#__PURE__*/_react.default.createElement(DatePickerPanelContainer, null, /*#__PURE__*/_react.default.createElement(DatePickerPanelMonths, null, /*#__PURE__*/_react.default.createElement(ArrowButton, {
|
58
89
|
variant: "small",
|
59
|
-
side: "left"
|
90
|
+
side: "left",
|
91
|
+
onClick: previousMonth,
|
92
|
+
disabled: previousDisabled
|
60
93
|
}, /*#__PURE__*/_react.default.createElement(_StyledOcticon.default, {
|
61
94
|
icon: _octiconsReact.ChevronLeftIcon,
|
62
95
|
color: "fg.muted"
|
63
96
|
})), /*#__PURE__*/_react.default.createElement(_Month.Month, {
|
64
|
-
month:
|
65
|
-
year:
|
97
|
+
month: currentViewingDate.getMonth(),
|
98
|
+
year: currentViewingDate.getFullYear()
|
66
99
|
}), configuration.view === '2-month' && /*#__PURE__*/_react.default.createElement(_Month.Month, {
|
67
|
-
month: (0, _dateFns.addMonths)(
|
68
|
-
year: (0, _dateFns.addMonths)(
|
100
|
+
month: (0, _dateFns.addMonths)(currentViewingDate, 1).getMonth(),
|
101
|
+
year: (0, _dateFns.addMonths)(currentViewingDate, 1).getFullYear()
|
69
102
|
}), /*#__PURE__*/_react.default.createElement(ArrowButton, {
|
70
103
|
variant: "small",
|
71
|
-
side: "right"
|
104
|
+
side: "right",
|
105
|
+
onClick: nextMonth,
|
106
|
+
disabled: nextDisabled
|
72
107
|
}, /*#__PURE__*/_react.default.createElement(_StyledOcticon.default, {
|
73
108
|
icon: _octiconsReact.ChevronRightIcon,
|
74
109
|
color: "fg.muted"
|
@@ -79,7 +114,8 @@ const DatePickerPanel = () => {
|
|
79
114
|
},
|
80
115
|
onClick: () => revertValue()
|
81
116
|
}, "Reset"), /*#__PURE__*/_react.default.createElement(_Button.default, {
|
82
|
-
variant: "small"
|
117
|
+
variant: "small",
|
118
|
+
onClick: () => goToMonth(new Date())
|
83
119
|
}, "Today")), configuration.confirmation && /*#__PURE__*/_react.default.createElement(_Button.ButtonPrimary, {
|
84
120
|
variant: "small",
|
85
121
|
onClick: () => saveValue()
|
package/lib/DatePicker/Day.js
CHANGED
@@ -120,7 +120,7 @@ const DayComponent = (0, _styledComponents.default)(DayBaseComponent).attrs(prop
|
|
120
120
|
})).withConfig({
|
121
121
|
displayName: "Day__DayComponent",
|
122
122
|
componentId: "sc-1japneh-1"
|
123
|
-
})(["background-color:", ";border-radius:", ";transition:0.
|
123
|
+
})(["background-color:", ";border-radius:", ";transition:0.1s background-color ease;& ", "{align-self:center;color:", ";display:flex;font-family:", ";font-size:", ";justify-self:center;user-select:none;transition:0.1s color ease;}&:hover{background-color:", ";cursor:pointer;transition:0.05s background-color ease;& ", "{color:", ";transition:0.1s color ease;}}&:active{background-color:", ";box-shadow:inset ", ";transition:0.1s background-color ease,0.1s box-shadow ease,0.1s color ease;& ", "{color:", ";transition:0.1s color ease;}}"], props => props.background, props => props.borderRadius, _Text.default, props => props.textColor, (0, _constants.get)('fonts.mono'), (0, _constants.get)('fontSizes.0'), props => props.backgroundHover, _Text.default, props => props.textColorHover, props => props.backgroundPressed, (0, _constants.get)('shadows.shadow.medium'), _Text.default, props => props.textColorPressed);
|
124
124
|
|
125
125
|
const Day = ({
|
126
126
|
date,
|
package/lib/DatePicker/Month.js
CHANGED
@@ -19,6 +19,8 @@ var _constants = require("../constants");
|
|
19
19
|
|
20
20
|
var _Day = require("./Day");
|
21
21
|
|
22
|
+
var _useDatePicker = _interopRequireDefault(require("./useDatePicker"));
|
23
|
+
|
22
24
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
23
25
|
|
24
26
|
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); }
|
@@ -42,17 +44,23 @@ const Month = ({
|
|
42
44
|
month,
|
43
45
|
year
|
44
46
|
}) => {
|
47
|
+
const {
|
48
|
+
configuration
|
49
|
+
} = (0, _useDatePicker.default)();
|
45
50
|
const [selectedDay, setSelectedDay] = (0, _react.useState)(null);
|
46
51
|
const getTitle = (0, _react.useMemo)(() => `${(0, _dateFns.format)(new Date(year, month), 'MMMM yyyy')}`, [month, year]);
|
47
52
|
const weekdayHeaders = (0, _react.useMemo)(() => {
|
48
53
|
const now = new Date(year, month);
|
54
|
+
const weekOptions = {
|
55
|
+
weekStartsOn: configuration.weekStartsOn === 'Sunday' ? 0 : 1
|
56
|
+
};
|
49
57
|
return (0, _dateFns.eachDayOfInterval)({
|
50
|
-
start: (0, _dateFns.startOfWeek)(now),
|
51
|
-
end: (0, _dateFns.endOfWeek)(now)
|
58
|
+
start: (0, _dateFns.startOfWeek)(now, weekOptions),
|
59
|
+
end: (0, _dateFns.endOfWeek)(now, weekOptions)
|
52
60
|
}).map(d => /*#__PURE__*/_react.default.createElement(WeekdayHeader, {
|
53
61
|
key: `weekday-${d}-header`
|
54
62
|
}, (0, _dateFns.format)(d, 'EEEEEE')));
|
55
|
-
}, [month, year]);
|
63
|
+
}, [configuration.weekStartsOn, month, year]);
|
56
64
|
|
57
65
|
const dayAction = date => {
|
58
66
|
setSelectedDay(date);
|
@@ -61,8 +69,9 @@ const Month = ({
|
|
61
69
|
const dayComponents = (0, _react.useMemo)(() => {
|
62
70
|
const components = [];
|
63
71
|
const firstDay = new Date(year, month, 1);
|
72
|
+
const preBlanks = configuration.weekStartsOn === 'Sunday' ? firstDay.getDay() : (firstDay.getDay() + 6) % 7;
|
64
73
|
|
65
|
-
for (let i = 0; i <
|
74
|
+
for (let i = 0; i < preBlanks; i++) {
|
66
75
|
components.push( /*#__PURE__*/_react.default.createElement(_Day.BlankDay, {
|
67
76
|
key: `month-pre-blank-${i}`
|
68
77
|
}));
|
@@ -79,15 +88,16 @@ const Month = ({
|
|
79
88
|
}
|
80
89
|
|
81
90
|
const lastDay = (0, _dateFns.lastDayOfMonth)(firstDay);
|
91
|
+
const postBlanks = configuration.weekStartsOn === 'Sunday' ? lastDay.getDay() : (lastDay.getDay() + 6) % 7;
|
82
92
|
|
83
|
-
for (let i = 6; i >
|
93
|
+
for (let i = 6; i > postBlanks; i--) {
|
84
94
|
components.push( /*#__PURE__*/_react.default.createElement(_Day.BlankDay, {
|
85
95
|
key: `month-post-blank-${i}`
|
86
96
|
}));
|
87
97
|
}
|
88
98
|
|
89
99
|
return components;
|
90
|
-
}, [month, selectedDay, year]);
|
100
|
+
}, [configuration.weekStartsOn, month, selectedDay, year]);
|
91
101
|
return /*#__PURE__*/_react.default.createElement(MonthComponent, {
|
92
102
|
role: "grid"
|
93
103
|
}, /*#__PURE__*/_react.default.createElement(MonthTitle, null, getTitle), weekdayHeaders, dayComponents);
|
@@ -9,12 +9,14 @@ export interface DatePickerConfiguration {
|
|
9
9
|
contiguousSelection?: boolean;
|
10
10
|
dateFormat?: DateFormat;
|
11
11
|
dimWeekends?: boolean;
|
12
|
+
iconPlacement?: 'start' | 'end' | 'none';
|
12
13
|
minDate?: Date;
|
13
14
|
maxDate?: Date;
|
14
15
|
placeholder?: string;
|
15
16
|
rangeIncrement?: number;
|
16
17
|
selection?: SelectionVariant;
|
17
18
|
view?: '1-month' | '2-month';
|
19
|
+
weekStartsOn?: 'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday';
|
18
20
|
}
|
19
21
|
export declare type RangeSelection = {
|
20
22
|
from: Date;
|
@@ -27,14 +29,18 @@ export declare type StringRangeSelection = {
|
|
27
29
|
export interface DatePickerContext {
|
28
30
|
disabled?: boolean;
|
29
31
|
configuration: DatePickerConfiguration;
|
32
|
+
currentViewingDate: Date;
|
33
|
+
goToMonth: (date: Date) => void;
|
30
34
|
hoverRange?: RangeSelection | null;
|
31
35
|
selection?: Selection;
|
32
36
|
softSelection?: Partial<RangeSelection> | null;
|
33
37
|
selectionActive?: boolean;
|
34
38
|
formattedDate: string;
|
39
|
+
nextMonth: () => void;
|
35
40
|
onSelection: (date: Date) => void;
|
36
41
|
onDayFocus: (date: Date) => void;
|
37
42
|
onDayBlur: (date: Date) => void;
|
43
|
+
previousMonth: () => void;
|
38
44
|
revertValue: () => void;
|
39
45
|
saveValue: (selection?: Selection) => void;
|
40
46
|
}
|
@@ -49,14 +55,18 @@ declare const useDatePicker: (date?: Date | undefined) => {
|
|
49
55
|
disabled: boolean;
|
50
56
|
selected: DaySelection;
|
51
57
|
configuration: DatePickerConfiguration;
|
58
|
+
currentViewingDate: Date;
|
59
|
+
goToMonth: (date: Date) => void;
|
52
60
|
hoverRange?: RangeSelection | null | undefined;
|
53
61
|
selection?: Selection | undefined;
|
54
62
|
softSelection?: Partial<RangeSelection> | null | undefined;
|
55
63
|
selectionActive?: boolean | undefined;
|
56
64
|
formattedDate: string;
|
65
|
+
nextMonth: () => void;
|
57
66
|
onSelection: (date: Date) => void;
|
58
67
|
onDayFocus: (date: Date) => void;
|
59
68
|
onDayBlur: (date: Date) => void;
|
69
|
+
previousMonth: () => void;
|
60
70
|
revertValue: () => void;
|
61
71
|
saveValue: (selection?: Selection | undefined) => void;
|
62
72
|
};
|
@@ -164,9 +164,11 @@ const defaultConfiguration = {
|
|
164
164
|
confirmation: false,
|
165
165
|
contiguousSelection: false,
|
166
166
|
dimWeekends: false,
|
167
|
+
iconPlacement: 'start',
|
167
168
|
placeholder: 'Select a Date...',
|
168
169
|
selection: 'single',
|
169
|
-
view: '2-month'
|
170
|
+
view: '2-month',
|
171
|
+
weekStartsOn: 'Sunday'
|
170
172
|
};
|
171
173
|
|
172
174
|
const DatePickerProvider = ({
|
@@ -179,11 +181,21 @@ const DatePickerProvider = ({
|
|
179
181
|
const [previousSelection, setPreviousSelection] = (0, _react.useState)(parseSelection(value, configuration.selection));
|
180
182
|
const [selection, setSelection] = (0, _react.useState)(parseSelection(value, configuration.selection));
|
181
183
|
const [hoverRange, setHoverRange] = (0, _react.useState)(null);
|
184
|
+
const [currentViewingDate, setCurrentViewingDate] = (0, _react.useState)(new Date());
|
182
185
|
(0, _react.useEffect)(() => {
|
183
186
|
setConfiguration((0, _deepmerge.default)(defaultConfiguration, externalConfig));
|
184
187
|
setSelection(parseSelection(selection, configuration.selection)); // Don't want this to run every time selection gets updated
|
185
188
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
186
189
|
}, [configuration.selection, externalConfig]);
|
190
|
+
const goToMonth = (0, _react.useCallback)(date => {
|
191
|
+
setCurrentViewingDate(new Date(new Date(date).toDateString()));
|
192
|
+
}, []);
|
193
|
+
const nextMonth = (0, _react.useCallback)(() => {
|
194
|
+
setCurrentViewingDate((0, _dateFns.addMonths)(currentViewingDate, 1));
|
195
|
+
}, [currentViewingDate]);
|
196
|
+
const previousMonth = (0, _react.useCallback)(() => {
|
197
|
+
setCurrentViewingDate((0, _dateFns.subMonths)(currentViewingDate, 1));
|
198
|
+
}, [currentViewingDate]);
|
187
199
|
const getFormattedDate = (0, _react.useMemo)(() => {
|
188
200
|
if (!selection) {
|
189
201
|
return configuration.placeholder;
|
@@ -191,7 +203,7 @@ const DatePickerProvider = ({
|
|
191
203
|
|
192
204
|
let template = 'MMM d';
|
193
205
|
|
194
|
-
if (configuration.dateFormat) {
|
206
|
+
if (configuration.anchorVariant !== 'input' && configuration.dateFormat) {
|
195
207
|
switch (configuration.dateFormat) {
|
196
208
|
case 'short':
|
197
209
|
template = 'MMM d';
|
@@ -205,6 +217,8 @@ const DatePickerProvider = ({
|
|
205
217
|
template = configuration.dateFormat;
|
206
218
|
break;
|
207
219
|
}
|
220
|
+
} else {
|
221
|
+
template = 'MM/dd/yyyy';
|
208
222
|
}
|
209
223
|
|
210
224
|
switch (configuration.selection) {
|
@@ -262,7 +276,7 @@ const DatePickerProvider = ({
|
|
262
276
|
return 'Invalid Configuration';
|
263
277
|
}
|
264
278
|
}
|
265
|
-
}, [configuration.dateFormat, configuration.placeholder, configuration.selection, selection]);
|
279
|
+
}, [configuration.anchorVariant, configuration.dateFormat, configuration.placeholder, configuration.selection, selection]);
|
266
280
|
const saveValue = (0, _react.useCallback)(updatedSelection => {
|
267
281
|
setPreviousSelection(updatedSelection !== null && updatedSelection !== void 0 ? updatedSelection : selection);
|
268
282
|
closePicker === null || closePicker === void 0 ? void 0 : closePicker();
|
@@ -336,18 +350,22 @@ const DatePickerProvider = ({
|
|
336
350
|
const datePickerCtx = (0, _react.useMemo)(() => {
|
337
351
|
return {
|
338
352
|
configuration,
|
353
|
+
currentViewingDate,
|
339
354
|
disabled: false,
|
340
355
|
formattedDate: getFormattedDate,
|
356
|
+
goToMonth,
|
341
357
|
hoverRange,
|
358
|
+
nextMonth,
|
342
359
|
onDayBlur: blurHnadler,
|
343
360
|
onDayFocus: focusHnadler,
|
344
361
|
onSelection: selectionHandler,
|
362
|
+
previousMonth,
|
345
363
|
revertValue,
|
346
364
|
saveValue,
|
347
365
|
selectionActive: false,
|
348
366
|
selection
|
349
367
|
};
|
350
|
-
}, [blurHnadler, configuration, focusHnadler, getFormattedDate, hoverRange, revertValue, saveValue, selection, selectionHandler]);
|
368
|
+
}, [blurHnadler, configuration, currentViewingDate, focusHnadler, getFormattedDate, goToMonth, hoverRange, nextMonth, previousMonth, revertValue, saveValue, selection, selectionHandler]);
|
351
369
|
return /*#__PURE__*/_react.default.createElement(DatePickerContext.Provider, {
|
352
370
|
value: datePickerCtx
|
353
371
|
}, children);
|
@@ -6,8 +6,11 @@ export const DatePicker = ({
|
|
6
6
|
anchorVariant,
|
7
7
|
anchorRef: externalAnchorRef,
|
8
8
|
confirmation,
|
9
|
+
dateFormat,
|
9
10
|
focusTrapSettings,
|
10
11
|
focusZoneSettings,
|
12
|
+
maxDate,
|
13
|
+
minDate,
|
11
14
|
onOpen: onOpenExternal,
|
12
15
|
onClose: onCloseExternal,
|
13
16
|
open,
|
@@ -15,15 +18,20 @@ export const DatePicker = ({
|
|
15
18
|
renderAnchor,
|
16
19
|
selection,
|
17
20
|
value,
|
18
|
-
view
|
21
|
+
view,
|
22
|
+
weekStartsOn
|
19
23
|
}) => {
|
20
24
|
const buttonRef = useRef(null);
|
21
25
|
const [isOpen, setIsOpen] = useState(false);
|
22
26
|
const datePickerConfiguration = {
|
23
27
|
anchorVariant,
|
24
28
|
confirmation,
|
29
|
+
dateFormat,
|
30
|
+
maxDate,
|
31
|
+
minDate,
|
25
32
|
selection,
|
26
|
-
view
|
33
|
+
view,
|
34
|
+
weekStartsOn
|
27
35
|
};
|
28
36
|
|
29
37
|
const onOpen = gesture => {
|
@@ -2,4 +2,4 @@ import React from 'react';
|
|
2
2
|
export interface DatePickerAnchorProps {
|
3
3
|
onAction?: (event?: React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>) => void;
|
4
4
|
}
|
5
|
-
export declare const DatePickerAnchor: React.ForwardRefExoticComponent<DatePickerAnchorProps & React.RefAttributes<
|
5
|
+
export declare const DatePickerAnchor: React.ForwardRefExoticComponent<DatePickerAnchorProps & React.RefAttributes<HTMLDivElement>>;
|
@@ -1,12 +1,13 @@
|
|
1
1
|
import { CalendarIcon } from '@primer/octicons-react';
|
2
2
|
import styled from 'styled-components';
|
3
3
|
import React, { useCallback } from 'react';
|
4
|
-
import Button from '../Button';
|
4
|
+
import Button, { ButtonInvisible } from '../Button';
|
5
5
|
import Text from '../Text';
|
6
6
|
import { get } from '../constants';
|
7
7
|
import StyledOcticon from '../StyledOcticon';
|
8
8
|
import useDatePicker from './useDatePicker';
|
9
9
|
import TextInput from '../TextInput';
|
10
|
+
import Box from '../Box';
|
10
11
|
const DatePickerAnchorButton = styled(Button).withConfig({
|
11
12
|
displayName: "DatePickerAnchor__DatePickerAnchorButton",
|
12
13
|
componentId: "sc-8gpb9d-0"
|
@@ -16,7 +17,8 @@ export const DatePickerAnchor = /*#__PURE__*/React.forwardRef(({
|
|
16
17
|
}, ref) => {
|
17
18
|
const {
|
18
19
|
configuration: {
|
19
|
-
anchorVariant
|
20
|
+
anchorVariant,
|
21
|
+
iconPlacement
|
20
22
|
},
|
21
23
|
disabled,
|
22
24
|
formattedDate
|
@@ -37,15 +39,61 @@ export const DatePickerAnchor = /*#__PURE__*/React.forwardRef(({
|
|
37
39
|
|
38
40
|
onAction === null || onAction === void 0 ? void 0 : onAction(event);
|
39
41
|
}, [disabled, onAction]);
|
42
|
+
const onKeyPressHandler = useCallback(e => {
|
43
|
+
console.log(e.currentTarget.value);
|
44
|
+
}, []);
|
45
|
+
const onInputChangeHandler = useCallback(e => {
|
46
|
+
console.log(e.currentTarget.value);
|
47
|
+
}, []);
|
40
48
|
|
41
49
|
if (anchorVariant === 'input') {
|
42
|
-
|
43
|
-
|
44
|
-
|
50
|
+
const calendarButton = side => /*#__PURE__*/React.createElement(ButtonInvisible, {
|
51
|
+
onClick: clickHandler,
|
52
|
+
sx: {
|
53
|
+
width: '32px',
|
54
|
+
px: '6px',
|
55
|
+
position: 'absolute',
|
56
|
+
[side]: '1px',
|
57
|
+
top: '1px'
|
58
|
+
}
|
59
|
+
}, /*#__PURE__*/React.createElement(StyledOcticon, {
|
60
|
+
icon: CalendarIcon
|
61
|
+
}));
|
62
|
+
|
63
|
+
const inputSx = () => {
|
64
|
+
if (iconPlacement === 'start') {
|
65
|
+
return {
|
66
|
+
pl: 5,
|
67
|
+
pr: 2
|
68
|
+
};
|
69
|
+
} else if (iconPlacement === 'end') {
|
70
|
+
return {
|
71
|
+
pl: 2,
|
72
|
+
pr: 5
|
73
|
+
};
|
74
|
+
} else {
|
75
|
+
return {};
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
return /*#__PURE__*/React.createElement(Box, {
|
80
|
+
ref: ref,
|
81
|
+
sx: {
|
82
|
+
position: 'relative',
|
83
|
+
display: 'flex',
|
84
|
+
flex: 1
|
85
|
+
}
|
86
|
+
}, iconPlacement === 'start' && calendarButton('left'), /*#__PURE__*/React.createElement(TextInput, {
|
87
|
+
defaultValue: formattedDate,
|
88
|
+
onKeyPress: onKeyPressHandler,
|
89
|
+
onChange: onInputChangeHandler,
|
90
|
+
sx: inputSx()
|
91
|
+
}), iconPlacement === 'end' && calendarButton('right'));
|
45
92
|
}
|
46
93
|
|
47
|
-
return /*#__PURE__*/React.createElement(
|
48
|
-
ref: ref
|
94
|
+
return /*#__PURE__*/React.createElement(Box, {
|
95
|
+
ref: ref
|
96
|
+
}, /*#__PURE__*/React.createElement(DatePickerAnchorButton, {
|
49
97
|
onClick: clickHandler,
|
50
98
|
onKeyPress: keyPressHandler
|
51
99
|
}, /*#__PURE__*/React.createElement(StyledOcticon, {
|
@@ -59,5 +107,5 @@ export const DatePickerAnchor = /*#__PURE__*/React.forwardRef(({
|
|
59
107
|
overflow: 'hidden',
|
60
108
|
textOverflow: 'ellipsis'
|
61
109
|
}
|
62
|
-
}, formattedDate));
|
110
|
+
}, formattedDate)));
|
63
111
|
});
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import { addMonths } from 'date-fns';
|
2
|
-
import React from 'react';
|
1
|
+
import { addMonths, subMonths } from 'date-fns';
|
2
|
+
import React, { useMemo } from 'react';
|
3
3
|
import Box from '../Box';
|
4
4
|
import { Month } from './Month';
|
5
5
|
import styled from 'styled-components';
|
@@ -28,23 +28,58 @@ export const DatePickerPanel = () => {
|
|
28
28
|
const {
|
29
29
|
configuration,
|
30
30
|
saveValue,
|
31
|
-
revertValue
|
31
|
+
revertValue,
|
32
|
+
currentViewingDate,
|
33
|
+
goToMonth,
|
34
|
+
nextMonth,
|
35
|
+
previousMonth
|
32
36
|
} = useDatePicker();
|
37
|
+
const previousDisabled = useMemo(() => {
|
38
|
+
const {
|
39
|
+
minDate
|
40
|
+
} = configuration;
|
41
|
+
if (!minDate) return false;
|
42
|
+
const previous = subMonths(currentViewingDate, 1);
|
43
|
+
|
44
|
+
if (minDate.getFullYear() >= previous.getFullYear() && minDate.getMonth() > previous.getMonth()) {
|
45
|
+
return true;
|
46
|
+
}
|
47
|
+
|
48
|
+
return false;
|
49
|
+
}, [configuration, currentViewingDate]);
|
50
|
+
const nextDisabled = useMemo(() => {
|
51
|
+
const {
|
52
|
+
maxDate,
|
53
|
+
view
|
54
|
+
} = configuration;
|
55
|
+
if (!maxDate) return false;
|
56
|
+
const next = addMonths(currentViewingDate, view === '2-month' ? 2 : 1);
|
57
|
+
|
58
|
+
if (maxDate.getFullYear() <= next.getFullYear() && maxDate.getMonth() < next.getMonth()) {
|
59
|
+
return true;
|
60
|
+
}
|
61
|
+
|
62
|
+
return false;
|
63
|
+
}, [configuration, currentViewingDate]);
|
33
64
|
return /*#__PURE__*/React.createElement(DatePickerPanelContainer, null, /*#__PURE__*/React.createElement(DatePickerPanelMonths, null, /*#__PURE__*/React.createElement(ArrowButton, {
|
34
65
|
variant: "small",
|
35
|
-
side: "left"
|
66
|
+
side: "left",
|
67
|
+
onClick: previousMonth,
|
68
|
+
disabled: previousDisabled
|
36
69
|
}, /*#__PURE__*/React.createElement(StyledOcticon, {
|
37
70
|
icon: ChevronLeftIcon,
|
38
71
|
color: "fg.muted"
|
39
72
|
})), /*#__PURE__*/React.createElement(Month, {
|
40
|
-
month:
|
41
|
-
year:
|
73
|
+
month: currentViewingDate.getMonth(),
|
74
|
+
year: currentViewingDate.getFullYear()
|
42
75
|
}), configuration.view === '2-month' && /*#__PURE__*/React.createElement(Month, {
|
43
|
-
month: addMonths(
|
44
|
-
year: addMonths(
|
76
|
+
month: addMonths(currentViewingDate, 1).getMonth(),
|
77
|
+
year: addMonths(currentViewingDate, 1).getFullYear()
|
45
78
|
}), /*#__PURE__*/React.createElement(ArrowButton, {
|
46
79
|
variant: "small",
|
47
|
-
side: "right"
|
80
|
+
side: "right",
|
81
|
+
onClick: nextMonth,
|
82
|
+
disabled: nextDisabled
|
48
83
|
}, /*#__PURE__*/React.createElement(StyledOcticon, {
|
49
84
|
icon: ChevronRightIcon,
|
50
85
|
color: "fg.muted"
|
@@ -55,7 +90,8 @@ export const DatePickerPanel = () => {
|
|
55
90
|
},
|
56
91
|
onClick: () => revertValue()
|
57
92
|
}, "Reset"), /*#__PURE__*/React.createElement(Button, {
|
58
|
-
variant: "small"
|
93
|
+
variant: "small",
|
94
|
+
onClick: () => goToMonth(new Date())
|
59
95
|
}, "Today")), configuration.confirmation && /*#__PURE__*/React.createElement(ButtonPrimary, {
|
60
96
|
variant: "small",
|
61
97
|
onClick: () => saveValue()
|
@@ -101,7 +101,7 @@ const DayComponent = styled(DayBaseComponent).attrs(props => ({
|
|
101
101
|
})).withConfig({
|
102
102
|
displayName: "Day__DayComponent",
|
103
103
|
componentId: "sc-1japneh-1"
|
104
|
-
})(["background-color:", ";border-radius:", ";transition:0.
|
104
|
+
})(["background-color:", ";border-radius:", ";transition:0.1s background-color ease;& ", "{align-self:center;color:", ";display:flex;font-family:", ";font-size:", ";justify-self:center;user-select:none;transition:0.1s color ease;}&:hover{background-color:", ";cursor:pointer;transition:0.05s background-color ease;& ", "{color:", ";transition:0.1s color ease;}}&:active{background-color:", ";box-shadow:inset ", ";transition:0.1s background-color ease,0.1s box-shadow ease,0.1s color ease;& ", "{color:", ";transition:0.1s color ease;}}"], props => props.background, props => props.borderRadius, Text, props => props.textColor, get('fonts.mono'), get('fontSizes.0'), props => props.backgroundHover, Text, props => props.textColorHover, props => props.backgroundPressed, get('shadows.shadow.medium'), Text, props => props.textColorPressed);
|
105
105
|
export const Day = ({
|
106
106
|
date,
|
107
107
|
onAction
|
@@ -5,6 +5,7 @@ import Box from '../Box';
|
|
5
5
|
import Text from '../Text';
|
6
6
|
import { get } from '../constants';
|
7
7
|
import { BlankDay, Day } from './Day';
|
8
|
+
import useDatePicker from './useDatePicker';
|
8
9
|
const MonthComponent = styled(Box).withConfig({
|
9
10
|
displayName: "Month__MonthComponent",
|
10
11
|
componentId: "l6j7o0-0"
|
@@ -21,17 +22,23 @@ export const Month = ({
|
|
21
22
|
month,
|
22
23
|
year
|
23
24
|
}) => {
|
25
|
+
const {
|
26
|
+
configuration
|
27
|
+
} = useDatePicker();
|
24
28
|
const [selectedDay, setSelectedDay] = useState(null);
|
25
29
|
const getTitle = useMemo(() => `${format(new Date(year, month), 'MMMM yyyy')}`, [month, year]);
|
26
30
|
const weekdayHeaders = useMemo(() => {
|
27
31
|
const now = new Date(year, month);
|
32
|
+
const weekOptions = {
|
33
|
+
weekStartsOn: configuration.weekStartsOn === 'Sunday' ? 0 : 1
|
34
|
+
};
|
28
35
|
return eachDayOfInterval({
|
29
|
-
start: startOfWeek(now),
|
30
|
-
end: endOfWeek(now)
|
36
|
+
start: startOfWeek(now, weekOptions),
|
37
|
+
end: endOfWeek(now, weekOptions)
|
31
38
|
}).map(d => /*#__PURE__*/React.createElement(WeekdayHeader, {
|
32
39
|
key: `weekday-${d}-header`
|
33
40
|
}, format(d, 'EEEEEE')));
|
34
|
-
}, [month, year]);
|
41
|
+
}, [configuration.weekStartsOn, month, year]);
|
35
42
|
|
36
43
|
const dayAction = date => {
|
37
44
|
setSelectedDay(date);
|
@@ -40,8 +47,9 @@ export const Month = ({
|
|
40
47
|
const dayComponents = useMemo(() => {
|
41
48
|
const components = [];
|
42
49
|
const firstDay = new Date(year, month, 1);
|
50
|
+
const preBlanks = configuration.weekStartsOn === 'Sunday' ? firstDay.getDay() : (firstDay.getDay() + 6) % 7;
|
43
51
|
|
44
|
-
for (let i = 0; i <
|
52
|
+
for (let i = 0; i < preBlanks; i++) {
|
45
53
|
components.push( /*#__PURE__*/React.createElement(BlankDay, {
|
46
54
|
key: `month-pre-blank-${i}`
|
47
55
|
}));
|
@@ -58,15 +66,16 @@ export const Month = ({
|
|
58
66
|
}
|
59
67
|
|
60
68
|
const lastDay = lastDayOfMonth(firstDay);
|
69
|
+
const postBlanks = configuration.weekStartsOn === 'Sunday' ? lastDay.getDay() : (lastDay.getDay() + 6) % 7;
|
61
70
|
|
62
|
-
for (let i = 6; i >
|
71
|
+
for (let i = 6; i > postBlanks; i--) {
|
63
72
|
components.push( /*#__PURE__*/React.createElement(BlankDay, {
|
64
73
|
key: `month-post-blank-${i}`
|
65
74
|
}));
|
66
75
|
}
|
67
76
|
|
68
77
|
return components;
|
69
|
-
}, [month, selectedDay, year]);
|
78
|
+
}, [configuration.weekStartsOn, month, selectedDay, year]);
|
70
79
|
return /*#__PURE__*/React.createElement(MonthComponent, {
|
71
80
|
role: "grid"
|
72
81
|
}, /*#__PURE__*/React.createElement(MonthTitle, null, getTitle), weekdayHeaders, dayComponents);
|
@@ -9,12 +9,14 @@ export interface DatePickerConfiguration {
|
|
9
9
|
contiguousSelection?: boolean;
|
10
10
|
dateFormat?: DateFormat;
|
11
11
|
dimWeekends?: boolean;
|
12
|
+
iconPlacement?: 'start' | 'end' | 'none';
|
12
13
|
minDate?: Date;
|
13
14
|
maxDate?: Date;
|
14
15
|
placeholder?: string;
|
15
16
|
rangeIncrement?: number;
|
16
17
|
selection?: SelectionVariant;
|
17
18
|
view?: '1-month' | '2-month';
|
19
|
+
weekStartsOn?: 'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday';
|
18
20
|
}
|
19
21
|
export declare type RangeSelection = {
|
20
22
|
from: Date;
|
@@ -27,14 +29,18 @@ export declare type StringRangeSelection = {
|
|
27
29
|
export interface DatePickerContext {
|
28
30
|
disabled?: boolean;
|
29
31
|
configuration: DatePickerConfiguration;
|
32
|
+
currentViewingDate: Date;
|
33
|
+
goToMonth: (date: Date) => void;
|
30
34
|
hoverRange?: RangeSelection | null;
|
31
35
|
selection?: Selection;
|
32
36
|
softSelection?: Partial<RangeSelection> | null;
|
33
37
|
selectionActive?: boolean;
|
34
38
|
formattedDate: string;
|
39
|
+
nextMonth: () => void;
|
35
40
|
onSelection: (date: Date) => void;
|
36
41
|
onDayFocus: (date: Date) => void;
|
37
42
|
onDayBlur: (date: Date) => void;
|
43
|
+
previousMonth: () => void;
|
38
44
|
revertValue: () => void;
|
39
45
|
saveValue: (selection?: Selection) => void;
|
40
46
|
}
|
@@ -49,14 +55,18 @@ declare const useDatePicker: (date?: Date | undefined) => {
|
|
49
55
|
disabled: boolean;
|
50
56
|
selected: DaySelection;
|
51
57
|
configuration: DatePickerConfiguration;
|
58
|
+
currentViewingDate: Date;
|
59
|
+
goToMonth: (date: Date) => void;
|
52
60
|
hoverRange?: RangeSelection | null | undefined;
|
53
61
|
selection?: Selection | undefined;
|
54
62
|
softSelection?: Partial<RangeSelection> | null | undefined;
|
55
63
|
selectionActive?: boolean | undefined;
|
56
64
|
formattedDate: string;
|
65
|
+
nextMonth: () => void;
|
57
66
|
onSelection: (date: Date) => void;
|
58
67
|
onDayFocus: (date: Date) => void;
|
59
68
|
onDayBlur: (date: Date) => void;
|
69
|
+
previousMonth: () => void;
|
60
70
|
revertValue: () => void;
|
61
71
|
saveValue: (selection?: Selection | undefined) => void;
|
62
72
|
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { format, isEqual, isAfter, isBefore } from 'date-fns';
|
1
|
+
import { format, isEqual, isAfter, isBefore, addMonths, subMonths } from 'date-fns';
|
2
2
|
import deepmerge from 'deepmerge';
|
3
3
|
import React, { createContext, useCallback, useContext, useMemo, useEffect, useState } from 'react';
|
4
4
|
const DatePickerContext = /*#__PURE__*/createContext(null);
|
@@ -139,9 +139,11 @@ const defaultConfiguration = {
|
|
139
139
|
confirmation: false,
|
140
140
|
contiguousSelection: false,
|
141
141
|
dimWeekends: false,
|
142
|
+
iconPlacement: 'start',
|
142
143
|
placeholder: 'Select a Date...',
|
143
144
|
selection: 'single',
|
144
|
-
view: '2-month'
|
145
|
+
view: '2-month',
|
146
|
+
weekStartsOn: 'Sunday'
|
145
147
|
};
|
146
148
|
export const DatePickerProvider = ({
|
147
149
|
configuration: externalConfig = {},
|
@@ -153,11 +155,21 @@ export const DatePickerProvider = ({
|
|
153
155
|
const [previousSelection, setPreviousSelection] = useState(parseSelection(value, configuration.selection));
|
154
156
|
const [selection, setSelection] = useState(parseSelection(value, configuration.selection));
|
155
157
|
const [hoverRange, setHoverRange] = useState(null);
|
158
|
+
const [currentViewingDate, setCurrentViewingDate] = useState(new Date());
|
156
159
|
useEffect(() => {
|
157
160
|
setConfiguration(deepmerge(defaultConfiguration, externalConfig));
|
158
161
|
setSelection(parseSelection(selection, configuration.selection)); // Don't want this to run every time selection gets updated
|
159
162
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
160
163
|
}, [configuration.selection, externalConfig]);
|
164
|
+
const goToMonth = useCallback(date => {
|
165
|
+
setCurrentViewingDate(new Date(new Date(date).toDateString()));
|
166
|
+
}, []);
|
167
|
+
const nextMonth = useCallback(() => {
|
168
|
+
setCurrentViewingDate(addMonths(currentViewingDate, 1));
|
169
|
+
}, [currentViewingDate]);
|
170
|
+
const previousMonth = useCallback(() => {
|
171
|
+
setCurrentViewingDate(subMonths(currentViewingDate, 1));
|
172
|
+
}, [currentViewingDate]);
|
161
173
|
const getFormattedDate = useMemo(() => {
|
162
174
|
if (!selection) {
|
163
175
|
return configuration.placeholder;
|
@@ -165,7 +177,7 @@ export const DatePickerProvider = ({
|
|
165
177
|
|
166
178
|
let template = 'MMM d';
|
167
179
|
|
168
|
-
if (configuration.dateFormat) {
|
180
|
+
if (configuration.anchorVariant !== 'input' && configuration.dateFormat) {
|
169
181
|
switch (configuration.dateFormat) {
|
170
182
|
case 'short':
|
171
183
|
template = 'MMM d';
|
@@ -179,6 +191,8 @@ export const DatePickerProvider = ({
|
|
179
191
|
template = configuration.dateFormat;
|
180
192
|
break;
|
181
193
|
}
|
194
|
+
} else {
|
195
|
+
template = 'MM/dd/yyyy';
|
182
196
|
}
|
183
197
|
|
184
198
|
switch (configuration.selection) {
|
@@ -236,7 +250,7 @@ export const DatePickerProvider = ({
|
|
236
250
|
return 'Invalid Configuration';
|
237
251
|
}
|
238
252
|
}
|
239
|
-
}, [configuration.dateFormat, configuration.placeholder, configuration.selection, selection]);
|
253
|
+
}, [configuration.anchorVariant, configuration.dateFormat, configuration.placeholder, configuration.selection, selection]);
|
240
254
|
const saveValue = useCallback(updatedSelection => {
|
241
255
|
setPreviousSelection(updatedSelection !== null && updatedSelection !== void 0 ? updatedSelection : selection);
|
242
256
|
closePicker === null || closePicker === void 0 ? void 0 : closePicker();
|
@@ -310,18 +324,22 @@ export const DatePickerProvider = ({
|
|
310
324
|
const datePickerCtx = useMemo(() => {
|
311
325
|
return {
|
312
326
|
configuration,
|
327
|
+
currentViewingDate,
|
313
328
|
disabled: false,
|
314
329
|
formattedDate: getFormattedDate,
|
330
|
+
goToMonth,
|
315
331
|
hoverRange,
|
332
|
+
nextMonth,
|
316
333
|
onDayBlur: blurHnadler,
|
317
334
|
onDayFocus: focusHnadler,
|
318
335
|
onSelection: selectionHandler,
|
336
|
+
previousMonth,
|
319
337
|
revertValue,
|
320
338
|
saveValue,
|
321
339
|
selectionActive: false,
|
322
340
|
selection
|
323
341
|
};
|
324
|
-
}, [blurHnadler, configuration, focusHnadler, getFormattedDate, hoverRange, revertValue, saveValue, selection, selectionHandler]);
|
342
|
+
}, [blurHnadler, configuration, currentViewingDate, focusHnadler, getFormattedDate, goToMonth, hoverRange, nextMonth, previousMonth, revertValue, saveValue, selection, selectionHandler]);
|
325
343
|
return /*#__PURE__*/React.createElement(DatePickerContext.Provider, {
|
326
344
|
value: datePickerCtx
|
327
345
|
}, children);
|