@codecademy/gamut 68.1.3-alpha.77d8dc.0 → 68.1.3-alpha.9e4fc9.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/DatePicker/Calendar/CalendarBody.js +11 -6
- package/dist/DatePicker/Calendar/types.d.ts +4 -0
- package/dist/DatePicker/Calendar/utils/keyHandler.d.ts +1 -1
- package/dist/DatePicker/Calendar/utils/keyHandler.js +15 -5
- package/dist/DatePicker/DatePicker.js +7 -27
- package/dist/DatePicker/DatePickerCalendar.js +7 -2
- package/dist/DatePicker/DatePickerInput.js +4 -2
- package/dist/DatePicker/translations.js +5 -1
- package/dist/DatePicker/types.d.ts +9 -1
- package/dist/DatePicker/utils.d.ts +3 -1
- package/dist/DatePicker/utils.js +29 -10
- package/package.json +2 -2
|
@@ -15,7 +15,7 @@ const TableHeader = /*#__PURE__*/_styled("th", {
|
|
|
15
15
|
fontWeight: 'base',
|
|
16
16
|
color: 'text-disabled',
|
|
17
17
|
textAlign: 'center'
|
|
18
|
-
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
18
|
+
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL0NhbGVuZGFyQm9keS50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZ0JvQiIsImZpbGUiOiIuLi8uLi8uLi9zcmMvRGF0ZVBpY2tlci9DYWxlbmRhci9DYWxlbmRhckJvZHkudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBzdGF0ZXMgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuaW1wb3J0IHsgdXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVmIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5pbXBvcnQgeyBUZXh0QnV0dG9uIH0gZnJvbSAnLi4vLi4vQnV0dG9uJztcbmltcG9ydCB7IENhbGVuZGFyQm9keVByb3BzIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1xuICBnZXRNb250aEdyaWQsXG4gIGlzRGF0ZURpc2FibGVkLFxuICBpc0RhdGVJblJhbmdlLFxuICBpc1NhbWVEYXksXG59IGZyb20gJy4vdXRpbHMvZGF0ZUdyaWQnO1xuaW1wb3J0IHsgZ2V0V2Vla2RheUZ1bGxOYW1lcywgZ2V0V2Vla2RheUxhYmVscyB9IGZyb20gJy4vdXRpbHMvZm9ybWF0JztcbmltcG9ydCB7IGdldERhdGVzV2l0aFJvdywga2V5SGFuZGxlciB9IGZyb20gJy4vdXRpbHMva2V5SGFuZGxlcic7XG5cbmNvbnN0IFRhYmxlSGVhZGVyID0gc3R5bGVkLnRoKFxuICBjc3Moe1xuICAgIGZvbnRTaXplOiAxNCxcbiAgICBmb250V2VpZ2h0OiAnYmFzZScsXG4gICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICB9KVxuKTtcblxuY29uc3QgRGF0ZUJ1dHRvbiA9IHN0eWxlZChUZXh0QnV0dG9uKShcbiAgc3RhdGVzKHtcbiAgICBpc1RvZGF5OiB7XG4gICAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAgICcmOjphZnRlcic6IHtcbiAgICAgICAgY29udGVudDogJ1wiXCInLFxuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgYm90dG9tOiA0LFxuICAgICAgICBsZWZ0OiAnNTAlJyxcbiAgICAgICAgd2lkdGg6IDQsXG4gICAgICAgIGhlaWdodDogNCxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAnZnVsbCcsXG4gICAgICAgIGJnOiAnaHlwZXInLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGlzU2VsZWN0ZWQ6IHtcbiAgICAgIGJnOiAndGV4dCcsXG4gICAgICBjb2xvcjogJ2JhY2tncm91bmQnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgaXNJblJhbmdlOiB7XG4gICAgICBiZzogJ3RleHQtZGlzYWJsZWQnLFxuICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIGJvcmRlclJhZGl1czogJ25vbmUnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGlzYWJsZWQ6IHtcbiAgICAgIGNvbG9yOiAndGV4dC1kaXNhYmxlZCcsXG4gICAgICB0ZXh0RGVjb3JhdGlvbjogJ2xpbmUtdGhyb3VnaCcsXG4gICAgICAnJjpob3Zlcic6IHtcbiAgICAgICAgdGV4dERlY29yYXRpb246ICdsaW5lLXRocm91Z2gnLFxuICAgICAgfSxcbiAgICB9LFxuICB9KSxcbiAgY3NzKHtcbiAgICBmb250V2VpZ2h0OiAnYmFzZScsXG4gICAgd2lkdGg6ICczMnB4JyxcbiAgfSlcbik7XG5cbmV4cG9ydCBjb25zdCBDYWxlbmRhckJvZHk6IFJlYWN0LkZDPENhbGVuZGFyQm9keVByb3BzPiA9ICh7XG4gIHZpc2libGVEYXRlLFxuICBzZWxlY3RlZERhdGUsXG4gIGVuZERhdGUgPSBudWxsLFxuICBkaXNhYmxlZERhdGVzID0gW10sXG4gIG9uRGF0ZVNlbGVjdCxcbiAgbG9jYWxlLFxuICB3ZWVrU3RhcnRzT24gPSAwLFxuICBsYWJlbGxlZEJ5SWQsXG4gIGZvY3VzZWREYXRlLFxuICBvbkZvY3VzZWREYXRlQ2hhbmdlLFxuICBvblZpc2libGVEYXRlQ2hhbmdlLFxuICBvbkVzY2FwZUtleVByZXNzLFxuICBoYXNBZGphY2VudE1vbnRoUmlnaHQsXG4gIGhhc0FkamFjZW50TW9udGhMZWZ0LFxufSkgPT4ge1xuICBjb25zdCB5ZWFyID0gdmlzaWJsZURhdGUuZ2V0RnVsbFllYXIoKTtcbiAgY29uc3QgbW9udGggPSB2aXNpYmxlRGF0ZS5nZXRNb250aCgpO1xuICBjb25zdCB3ZWVrcyA9IGdldE1vbnRoR3JpZCh5ZWFyLCBtb250aCwgd2Vla1N0YXJ0c09uKTtcbiAgY29uc3Qgd2Vla2RheUxhYmVscyA9IGdldFdlZWtkYXlMYWJlbHMobG9jYWxlLCB3ZWVrU3RhcnRzT24pO1xuICBjb25zdCB3ZWVrZGF5RnVsbE5hbWVzID0gZ2V0V2Vla2RheUZ1bGxOYW1lcyhsb2NhbGUsIHdlZWtTdGFydHNPbik7XG4gIGNvbnN0IGJ1dHRvblJlZnMgPSB1c2VSZWY8TWFwPG51bWJlciwgSFRNTEVsZW1lbnQ+PihuZXcgTWFwKCkpO1xuXG4gIGNvbnN0IGRhdGVzV2l0aFJvdyA9IHVzZU1lbW8oKCkgPT4gZ2V0RGF0ZXNXaXRoUm93KHdlZWtzKSwgW3dlZWtzXSk7XG4gIGNvbnN0IGZvY3VzVGFyZ2V0ID0gZm9jdXNlZERhdGUgPz8gc2VsZWN0ZWREYXRlO1xuXG4gIGNvbnN0IGlzVG9kYXkgPSB1c2VDYWxsYmFjayhcbiAgICAoZGF0ZTogRGF0ZSB8IG51bGwpID0+IGRhdGUgIT09IG51bGwgJiYgaXNTYW1lRGF5KGRhdGUsIG5ldyBEYXRlKCkpLFxuICAgIFtdXG4gICk7XG5cbiAgY29uc3QgZm9jdXNCdXR0b24gPSB1c2VDYWxsYmFjaygoZGF0ZTogRGF0ZSB8IG51bGwpID0+IHtcbiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuO1xuICAgIGNvbnN0IGtleSA9IG5ldyBEYXRlKFxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgZGF0ZS5nZXREYXRlKClcbiAgICApLmdldFRpbWUoKTtcbiAgICBidXR0b25SZWZzLmN1cnJlbnQuZ2V0KGtleSk/LmZvY3VzKCk7XG4gIH0sIFtdKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChmb2N1c1RhcmdldCAhPT0gbnVsbCkgZm9jdXNCdXR0b24oZm9jdXNUYXJnZXQpO1xuICB9LCBbZm9jdXNUYXJnZXQsIGZvY3VzQnV0dG9uXSk7XG5cbiAgY29uc3QgaGFuZGxlS2V5RG93biA9IHVzZUNhbGxiYWNrKFxuICAgIChlOiBSZWFjdC5LZXlib2FyZEV2ZW50LCBkYXRlOiBEYXRlKSA9PlxuICAgICAga2V5SGFuZGxlcihcbiAgICAgICAgZSxcbiAgICAgICAgZGF0ZSxcbiAgICAgICAgb25Gb2N1c2VkRGF0ZUNoYW5nZSxcbiAgICAgICAgZGF0ZXNXaXRoUm93LFxuICAgICAgICBtb250aCxcbiAgICAgICAgeWVhcixcbiAgICAgICAgZGlzYWJsZWREYXRlcyxcbiAgICAgICAgb25EYXRlU2VsZWN0LFxuICAgICAgICBvbkVzY2FwZUtleVByZXNzLFxuICAgICAgICBvblZpc2libGVEYXRlQ2hhbmdlLFxuICAgICAgICBoYXNBZGphY2VudE1vbnRoUmlnaHQsXG4gICAgICAgIGhhc0FkamFjZW50TW9udGhMZWZ0XG4gICAgICApLFxuICAgIFtcbiAgICAgIG9uRm9jdXNlZERhdGVDaGFuZ2UsXG4gICAgICBkYXRlc1dpdGhSb3csXG4gICAgICBtb250aCxcbiAgICAgIHllYXIsXG4gICAgICBkaXNhYmxlZERhdGVzLFxuICAgICAgb25EYXRlU2VsZWN0LFxuICAgICAgb25Fc2NhcGVLZXlQcmVzcyxcbiAgICAgIG9uVmlzaWJsZURhdGVDaGFuZ2UsXG4gICAgICBoYXNBZGphY2VudE1vbnRoTGVmdCxcbiAgICAgIGhhc0FkamFjZW50TW9udGhSaWdodCxcbiAgICBdXG4gICk7XG5cbiAgY29uc3Qgc2V0QnV0dG9uUmVmID0gdXNlQ2FsbGJhY2soKGRhdGU6IERhdGUsIGVsOiBIVE1MRWxlbWVudCB8IG51bGwpID0+IHtcbiAgICBjb25zdCBrID0gbmV3IERhdGUoXG4gICAgICBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgICBkYXRlLmdldE1vbnRoKCksXG4gICAgICBkYXRlLmdldERhdGUoKVxuICAgICkuZ2V0VGltZSgpO1xuICAgIGlmIChlbCkgYnV0dG9uUmVmcy5jdXJyZW50LnNldChrLCBlbCk7XG4gICAgZWxzZSBidXR0b25SZWZzLmN1cnJlbnQuZGVsZXRlKGspO1xuICB9LCBbXSk7XG5cbiAgcmV0dXJuIChcbiAgICA8dGFibGUgYXJpYS1sYWJlbGxlZGJ5PXtsYWJlbGxlZEJ5SWR9IHJvbGU9XCJncmlkXCIgd2lkdGg9XCIxMDAlXCI+XG4gICAgICA8dGhlYWQ+XG4gICAgICAgIDx0cj5cbiAgICAgICAgICB7d2Vla2RheUxhYmVscy5tYXAoKGxhYmVsLCBpKSA9PiAoXG4gICAgICAgICAgICA8VGFibGVIZWFkZXIgYWJicj17d2Vla2RheUZ1bGxOYW1lc1tpXX0ga2V5PXtsYWJlbH0gc2NvcGU9XCJjb2xcIj5cbiAgICAgICAgICAgICAge2xhYmVsfVxuICAgICAgICAgICAgPC9UYWJsZUhlYWRlcj5cbiAgICAgICAgICApKX1cbiAgICAgICAgPC90cj5cbiAgICAgIDwvdGhlYWQ+XG4gICAgICA8dGJvZHk+XG4gICAgICAgIHt3ZWVrcy5tYXAoKHdlZWssIHJvd0luZGV4KSA9PiAoXG4gICAgICAgICAgPHRyIGtleT17d2Vlay5qb2luKCctJyl9PlxuICAgICAgICAgICAge3dlZWsubWFwKChkYXRlLCBjb2xJbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoZGF0ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAvLyBmaXggdGhpcyBlcnJvclxuICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlYWN0L25vLWFycmF5LWluZGV4LWtleSwganN4LWExMXkvY29udHJvbC1oYXMtYXNzb2NpYXRlZC1sYWJlbFxuICAgICAgICAgICAgICAgICAgPHRkIGtleT17YGVtcHR5LSR7cm93SW5kZXh9LSR7Y29sSW5kZXh9YH0gcm9sZT1cImdyaWRjZWxsXCIgLz5cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkID1cbiAgICAgICAgICAgICAgICBpc1NhbWVEYXkoZGF0ZSwgc2VsZWN0ZWREYXRlKSB8fCBpc1NhbWVEYXkoZGF0ZSwgZW5kRGF0ZSk7XG4gICAgICAgICAgICAgIGNvbnN0IGluUmFuZ2UgPVxuICAgICAgICAgICAgICAgICEhc2VsZWN0ZWREYXRlICYmXG4gICAgICAgICAgICAgICAgISFlbmREYXRlICYmXG4gICAgICAgICAgICAgICAgaXNEYXRlSW5SYW5nZShkYXRlLCBzZWxlY3RlZERhdGUsIGVuZERhdGUpO1xuICAgICAgICAgICAgICBjb25zdCBkaXNhYmxlZCA9IGlzRGF0ZURpc2FibGVkKGRhdGUsIGRpc2FibGVkRGF0ZXMpO1xuICAgICAgICAgICAgICBjb25zdCB0b2RheSA9IGlzVG9kYXkoZGF0ZSk7XG4gICAgICAgICAgICAgIC8vIHRoaXMgaXMgbWFraW5nIHRoZSBzZWxlY3RlZCBkYXRlIGEgZGlmZmVybmV0IGNvbG9yIGJjIGl0IGlzIGZvY3VzZWQsIGxvb2sgaW50byBmdXJ0aGVyXG4gICAgICAgICAgICAgIGNvbnN0IGlzRm9jdXNlZCA9XG4gICAgICAgICAgICAgICAgZm9jdXNUYXJnZXQgIT09IG51bGwgJiYgaXNTYW1lRGF5KGRhdGUsIGZvY3VzVGFyZ2V0KTtcblxuICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDx0ZFxuICAgICAgICAgICAgICAgICAgYXJpYS1zZWxlY3RlZD17c2VsZWN0ZWR9XG4gICAgICAgICAgICAgICAgICBrZXk9e2RhdGUuZ2V0VGltZSgpfVxuICAgICAgICAgICAgICAgICAgcm9sZT1cImdyaWRjZWxsXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8RGF0ZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17ZGlzYWJsZWR9XG4gICAgICAgICAgICAgICAgICAgIGlzSW5SYW5nZT17aW5SYW5nZX1cbiAgICAgICAgICAgICAgICAgICAgaXNTZWxlY3RlZD17c2VsZWN0ZWR9XG4gICAgICAgICAgICAgICAgICAgIGlzVG9kYXk9e3RvZGF5fVxuICAgICAgICAgICAgICAgICAgICByZWY9eyhlbCkgPT4gc2V0QnV0dG9uUmVmKGRhdGUsIGVsIGFzIEhUTUxFbGVtZW50IHwgbnVsbCl9XG4gICAgICAgICAgICAgICAgICAgIHRhYkluZGV4PXtpc0ZvY3VzZWQgPyAwIDogLTF9XG4gICAgICAgICAgICAgICAgICAgIHZhcmlhbnQ9XCJzZWNvbmRhcnlcIlxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBvbkRhdGVTZWxlY3QoZGF0ZSl9XG4gICAgICAgICAgICAgICAgICAgIG9uRm9jdXM9eygpID0+IG9uRm9jdXNlZERhdGVDaGFuZ2U/LihkYXRlKX1cbiAgICAgICAgICAgICAgICAgICAgb25LZXlEb3duPXsoZTogUmVhY3QuS2V5Ym9hcmRFdmVudCkgPT5cbiAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVLZXlEb3duKGUsIGRhdGUpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAge2RhdGUuZ2V0RGF0ZSgpfVxuICAgICAgICAgICAgICAgICAgPC9EYXRlQnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KX1cbiAgICAgICAgICA8L3RyPlxuICAgICAgICApKX1cbiAgICAgIDwvdGJvZHk+XG4gICAgPC90YWJsZT5cbiAgKTtcbn07XG4iXX0= */");
|
|
19
19
|
const DateButton = /*#__PURE__*/_styled(TextButton, {
|
|
20
20
|
target: "e12sl4cx0",
|
|
21
21
|
label: "DateButton"
|
|
@@ -58,12 +58,15 @@ const DateButton = /*#__PURE__*/_styled(TextButton, {
|
|
|
58
58
|
},
|
|
59
59
|
disabled: {
|
|
60
60
|
color: 'text-disabled',
|
|
61
|
-
textDecoration: 'line-through'
|
|
61
|
+
textDecoration: 'line-through',
|
|
62
|
+
'&:hover': {
|
|
63
|
+
textDecoration: 'line-through'
|
|
64
|
+
}
|
|
62
65
|
}
|
|
63
66
|
}), css({
|
|
64
67
|
fontWeight: 'base',
|
|
65
68
|
width: '32px'
|
|
66
|
-
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
69
|
+
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL0NhbGVuZGFyQm9keS50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBeUJtQiIsImZpbGUiOiIuLi8uLi8uLi9zcmMvRGF0ZVBpY2tlci9DYWxlbmRhci9DYWxlbmRhckJvZHkudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBzdGF0ZXMgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuaW1wb3J0IHsgdXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVmIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5pbXBvcnQgeyBUZXh0QnV0dG9uIH0gZnJvbSAnLi4vLi4vQnV0dG9uJztcbmltcG9ydCB7IENhbGVuZGFyQm9keVByb3BzIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1xuICBnZXRNb250aEdyaWQsXG4gIGlzRGF0ZURpc2FibGVkLFxuICBpc0RhdGVJblJhbmdlLFxuICBpc1NhbWVEYXksXG59IGZyb20gJy4vdXRpbHMvZGF0ZUdyaWQnO1xuaW1wb3J0IHsgZ2V0V2Vla2RheUZ1bGxOYW1lcywgZ2V0V2Vla2RheUxhYmVscyB9IGZyb20gJy4vdXRpbHMvZm9ybWF0JztcbmltcG9ydCB7IGdldERhdGVzV2l0aFJvdywga2V5SGFuZGxlciB9IGZyb20gJy4vdXRpbHMva2V5SGFuZGxlcic7XG5cbmNvbnN0IFRhYmxlSGVhZGVyID0gc3R5bGVkLnRoKFxuICBjc3Moe1xuICAgIGZvbnRTaXplOiAxNCxcbiAgICBmb250V2VpZ2h0OiAnYmFzZScsXG4gICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICB9KVxuKTtcblxuY29uc3QgRGF0ZUJ1dHRvbiA9IHN0eWxlZChUZXh0QnV0dG9uKShcbiAgc3RhdGVzKHtcbiAgICBpc1RvZGF5OiB7XG4gICAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAgICcmOjphZnRlcic6IHtcbiAgICAgICAgY29udGVudDogJ1wiXCInLFxuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgYm90dG9tOiA0LFxuICAgICAgICBsZWZ0OiAnNTAlJyxcbiAgICAgICAgd2lkdGg6IDQsXG4gICAgICAgIGhlaWdodDogNCxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAnZnVsbCcsXG4gICAgICAgIGJnOiAnaHlwZXInLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGlzU2VsZWN0ZWQ6IHtcbiAgICAgIGJnOiAndGV4dCcsXG4gICAgICBjb2xvcjogJ2JhY2tncm91bmQnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgaXNJblJhbmdlOiB7XG4gICAgICBiZzogJ3RleHQtZGlzYWJsZWQnLFxuICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIGJvcmRlclJhZGl1czogJ25vbmUnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGlzYWJsZWQ6IHtcbiAgICAgIGNvbG9yOiAndGV4dC1kaXNhYmxlZCcsXG4gICAgICB0ZXh0RGVjb3JhdGlvbjogJ2xpbmUtdGhyb3VnaCcsXG4gICAgICAnJjpob3Zlcic6IHtcbiAgICAgICAgdGV4dERlY29yYXRpb246ICdsaW5lLXRocm91Z2gnLFxuICAgICAgfSxcbiAgICB9LFxuICB9KSxcbiAgY3NzKHtcbiAgICBmb250V2VpZ2h0OiAnYmFzZScsXG4gICAgd2lkdGg6ICczMnB4JyxcbiAgfSlcbik7XG5cbmV4cG9ydCBjb25zdCBDYWxlbmRhckJvZHk6IFJlYWN0LkZDPENhbGVuZGFyQm9keVByb3BzPiA9ICh7XG4gIHZpc2libGVEYXRlLFxuICBzZWxlY3RlZERhdGUsXG4gIGVuZERhdGUgPSBudWxsLFxuICBkaXNhYmxlZERhdGVzID0gW10sXG4gIG9uRGF0ZVNlbGVjdCxcbiAgbG9jYWxlLFxuICB3ZWVrU3RhcnRzT24gPSAwLFxuICBsYWJlbGxlZEJ5SWQsXG4gIGZvY3VzZWREYXRlLFxuICBvbkZvY3VzZWREYXRlQ2hhbmdlLFxuICBvblZpc2libGVEYXRlQ2hhbmdlLFxuICBvbkVzY2FwZUtleVByZXNzLFxuICBoYXNBZGphY2VudE1vbnRoUmlnaHQsXG4gIGhhc0FkamFjZW50TW9udGhMZWZ0LFxufSkgPT4ge1xuICBjb25zdCB5ZWFyID0gdmlzaWJsZURhdGUuZ2V0RnVsbFllYXIoKTtcbiAgY29uc3QgbW9udGggPSB2aXNpYmxlRGF0ZS5nZXRNb250aCgpO1xuICBjb25zdCB3ZWVrcyA9IGdldE1vbnRoR3JpZCh5ZWFyLCBtb250aCwgd2Vla1N0YXJ0c09uKTtcbiAgY29uc3Qgd2Vla2RheUxhYmVscyA9IGdldFdlZWtkYXlMYWJlbHMobG9jYWxlLCB3ZWVrU3RhcnRzT24pO1xuICBjb25zdCB3ZWVrZGF5RnVsbE5hbWVzID0gZ2V0V2Vla2RheUZ1bGxOYW1lcyhsb2NhbGUsIHdlZWtTdGFydHNPbik7XG4gIGNvbnN0IGJ1dHRvblJlZnMgPSB1c2VSZWY8TWFwPG51bWJlciwgSFRNTEVsZW1lbnQ+PihuZXcgTWFwKCkpO1xuXG4gIGNvbnN0IGRhdGVzV2l0aFJvdyA9IHVzZU1lbW8oKCkgPT4gZ2V0RGF0ZXNXaXRoUm93KHdlZWtzKSwgW3dlZWtzXSk7XG4gIGNvbnN0IGZvY3VzVGFyZ2V0ID0gZm9jdXNlZERhdGUgPz8gc2VsZWN0ZWREYXRlO1xuXG4gIGNvbnN0IGlzVG9kYXkgPSB1c2VDYWxsYmFjayhcbiAgICAoZGF0ZTogRGF0ZSB8IG51bGwpID0+IGRhdGUgIT09IG51bGwgJiYgaXNTYW1lRGF5KGRhdGUsIG5ldyBEYXRlKCkpLFxuICAgIFtdXG4gICk7XG5cbiAgY29uc3QgZm9jdXNCdXR0b24gPSB1c2VDYWxsYmFjaygoZGF0ZTogRGF0ZSB8IG51bGwpID0+IHtcbiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuO1xuICAgIGNvbnN0IGtleSA9IG5ldyBEYXRlKFxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgZGF0ZS5nZXRNb250aCgpLFxuICAgICAgZGF0ZS5nZXREYXRlKClcbiAgICApLmdldFRpbWUoKTtcbiAgICBidXR0b25SZWZzLmN1cnJlbnQuZ2V0KGtleSk/LmZvY3VzKCk7XG4gIH0sIFtdKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmIChmb2N1c1RhcmdldCAhPT0gbnVsbCkgZm9jdXNCdXR0b24oZm9jdXNUYXJnZXQpO1xuICB9LCBbZm9jdXNUYXJnZXQsIGZvY3VzQnV0dG9uXSk7XG5cbiAgY29uc3QgaGFuZGxlS2V5RG93biA9IHVzZUNhbGxiYWNrKFxuICAgIChlOiBSZWFjdC5LZXlib2FyZEV2ZW50LCBkYXRlOiBEYXRlKSA9PlxuICAgICAga2V5SGFuZGxlcihcbiAgICAgICAgZSxcbiAgICAgICAgZGF0ZSxcbiAgICAgICAgb25Gb2N1c2VkRGF0ZUNoYW5nZSxcbiAgICAgICAgZGF0ZXNXaXRoUm93LFxuICAgICAgICBtb250aCxcbiAgICAgICAgeWVhcixcbiAgICAgICAgZGlzYWJsZWREYXRlcyxcbiAgICAgICAgb25EYXRlU2VsZWN0LFxuICAgICAgICBvbkVzY2FwZUtleVByZXNzLFxuICAgICAgICBvblZpc2libGVEYXRlQ2hhbmdlLFxuICAgICAgICBoYXNBZGphY2VudE1vbnRoUmlnaHQsXG4gICAgICAgIGhhc0FkamFjZW50TW9udGhMZWZ0XG4gICAgICApLFxuICAgIFtcbiAgICAgIG9uRm9jdXNlZERhdGVDaGFuZ2UsXG4gICAgICBkYXRlc1dpdGhSb3csXG4gICAgICBtb250aCxcbiAgICAgIHllYXIsXG4gICAgICBkaXNhYmxlZERhdGVzLFxuICAgICAgb25EYXRlU2VsZWN0LFxuICAgICAgb25Fc2NhcGVLZXlQcmVzcyxcbiAgICAgIG9uVmlzaWJsZURhdGVDaGFuZ2UsXG4gICAgICBoYXNBZGphY2VudE1vbnRoTGVmdCxcbiAgICAgIGhhc0FkamFjZW50TW9udGhSaWdodCxcbiAgICBdXG4gICk7XG5cbiAgY29uc3Qgc2V0QnV0dG9uUmVmID0gdXNlQ2FsbGJhY2soKGRhdGU6IERhdGUsIGVsOiBIVE1MRWxlbWVudCB8IG51bGwpID0+IHtcbiAgICBjb25zdCBrID0gbmV3IERhdGUoXG4gICAgICBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgICBkYXRlLmdldE1vbnRoKCksXG4gICAgICBkYXRlLmdldERhdGUoKVxuICAgICkuZ2V0VGltZSgpO1xuICAgIGlmIChlbCkgYnV0dG9uUmVmcy5jdXJyZW50LnNldChrLCBlbCk7XG4gICAgZWxzZSBidXR0b25SZWZzLmN1cnJlbnQuZGVsZXRlKGspO1xuICB9LCBbXSk7XG5cbiAgcmV0dXJuIChcbiAgICA8dGFibGUgYXJpYS1sYWJlbGxlZGJ5PXtsYWJlbGxlZEJ5SWR9IHJvbGU9XCJncmlkXCIgd2lkdGg9XCIxMDAlXCI+XG4gICAgICA8dGhlYWQ+XG4gICAgICAgIDx0cj5cbiAgICAgICAgICB7d2Vla2RheUxhYmVscy5tYXAoKGxhYmVsLCBpKSA9PiAoXG4gICAgICAgICAgICA8VGFibGVIZWFkZXIgYWJicj17d2Vla2RheUZ1bGxOYW1lc1tpXX0ga2V5PXtsYWJlbH0gc2NvcGU9XCJjb2xcIj5cbiAgICAgICAgICAgICAge2xhYmVsfVxuICAgICAgICAgICAgPC9UYWJsZUhlYWRlcj5cbiAgICAgICAgICApKX1cbiAgICAgICAgPC90cj5cbiAgICAgIDwvdGhlYWQ+XG4gICAgICA8dGJvZHk+XG4gICAgICAgIHt3ZWVrcy5tYXAoKHdlZWssIHJvd0luZGV4KSA9PiAoXG4gICAgICAgICAgPHRyIGtleT17d2Vlay5qb2luKCctJyl9PlxuICAgICAgICAgICAge3dlZWsubWFwKChkYXRlLCBjb2xJbmRleCkgPT4ge1xuICAgICAgICAgICAgICBpZiAoZGF0ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAvLyBmaXggdGhpcyBlcnJvclxuICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlYWN0L25vLWFycmF5LWluZGV4LWtleSwganN4LWExMXkvY29udHJvbC1oYXMtYXNzb2NpYXRlZC1sYWJlbFxuICAgICAgICAgICAgICAgICAgPHRkIGtleT17YGVtcHR5LSR7cm93SW5kZXh9LSR7Y29sSW5kZXh9YH0gcm9sZT1cImdyaWRjZWxsXCIgLz5cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkID1cbiAgICAgICAgICAgICAgICBpc1NhbWVEYXkoZGF0ZSwgc2VsZWN0ZWREYXRlKSB8fCBpc1NhbWVEYXkoZGF0ZSwgZW5kRGF0ZSk7XG4gICAgICAgICAgICAgIGNvbnN0IGluUmFuZ2UgPVxuICAgICAgICAgICAgICAgICEhc2VsZWN0ZWREYXRlICYmXG4gICAgICAgICAgICAgICAgISFlbmREYXRlICYmXG4gICAgICAgICAgICAgICAgaXNEYXRlSW5SYW5nZShkYXRlLCBzZWxlY3RlZERhdGUsIGVuZERhdGUpO1xuICAgICAgICAgICAgICBjb25zdCBkaXNhYmxlZCA9IGlzRGF0ZURpc2FibGVkKGRhdGUsIGRpc2FibGVkRGF0ZXMpO1xuICAgICAgICAgICAgICBjb25zdCB0b2RheSA9IGlzVG9kYXkoZGF0ZSk7XG4gICAgICAgICAgICAgIC8vIHRoaXMgaXMgbWFraW5nIHRoZSBzZWxlY3RlZCBkYXRlIGEgZGlmZmVybmV0IGNvbG9yIGJjIGl0IGlzIGZvY3VzZWQsIGxvb2sgaW50byBmdXJ0aGVyXG4gICAgICAgICAgICAgIGNvbnN0IGlzRm9jdXNlZCA9XG4gICAgICAgICAgICAgICAgZm9jdXNUYXJnZXQgIT09IG51bGwgJiYgaXNTYW1lRGF5KGRhdGUsIGZvY3VzVGFyZ2V0KTtcblxuICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDx0ZFxuICAgICAgICAgICAgICAgICAgYXJpYS1zZWxlY3RlZD17c2VsZWN0ZWR9XG4gICAgICAgICAgICAgICAgICBrZXk9e2RhdGUuZ2V0VGltZSgpfVxuICAgICAgICAgICAgICAgICAgcm9sZT1cImdyaWRjZWxsXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICA8RGF0ZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17ZGlzYWJsZWR9XG4gICAgICAgICAgICAgICAgICAgIGlzSW5SYW5nZT17aW5SYW5nZX1cbiAgICAgICAgICAgICAgICAgICAgaXNTZWxlY3RlZD17c2VsZWN0ZWR9XG4gICAgICAgICAgICAgICAgICAgIGlzVG9kYXk9e3RvZGF5fVxuICAgICAgICAgICAgICAgICAgICByZWY9eyhlbCkgPT4gc2V0QnV0dG9uUmVmKGRhdGUsIGVsIGFzIEhUTUxFbGVtZW50IHwgbnVsbCl9XG4gICAgICAgICAgICAgICAgICAgIHRhYkluZGV4PXtpc0ZvY3VzZWQgPyAwIDogLTF9XG4gICAgICAgICAgICAgICAgICAgIHZhcmlhbnQ9XCJzZWNvbmRhcnlcIlxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiBvbkRhdGVTZWxlY3QoZGF0ZSl9XG4gICAgICAgICAgICAgICAgICAgIG9uRm9jdXM9eygpID0+IG9uRm9jdXNlZERhdGVDaGFuZ2U/LihkYXRlKX1cbiAgICAgICAgICAgICAgICAgICAgb25LZXlEb3duPXsoZTogUmVhY3QuS2V5Ym9hcmRFdmVudCkgPT5cbiAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVLZXlEb3duKGUsIGRhdGUpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAge2RhdGUuZ2V0RGF0ZSgpfVxuICAgICAgICAgICAgICAgICAgPC9EYXRlQnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KX1cbiAgICAgICAgICA8L3RyPlxuICAgICAgICApKX1cbiAgICAgIDwvdGJvZHk+XG4gICAgPC90YWJsZT5cbiAgKTtcbn07XG4iXX0= */");
|
|
67
70
|
export const CalendarBody = ({
|
|
68
71
|
visibleDate,
|
|
69
72
|
selectedDate,
|
|
@@ -76,7 +79,9 @@ export const CalendarBody = ({
|
|
|
76
79
|
focusedDate,
|
|
77
80
|
onFocusedDateChange,
|
|
78
81
|
onVisibleDateChange,
|
|
79
|
-
onEscapeKeyPress
|
|
82
|
+
onEscapeKeyPress,
|
|
83
|
+
hasAdjacentMonthRight,
|
|
84
|
+
hasAdjacentMonthLeft
|
|
80
85
|
}) => {
|
|
81
86
|
const year = visibleDate.getFullYear();
|
|
82
87
|
const month = visibleDate.getMonth();
|
|
@@ -86,7 +91,7 @@ export const CalendarBody = ({
|
|
|
86
91
|
const buttonRefs = useRef(new Map());
|
|
87
92
|
const datesWithRow = useMemo(() => getDatesWithRow(weeks), [weeks]);
|
|
88
93
|
const focusTarget = focusedDate ?? selectedDate;
|
|
89
|
-
const isToday = useCallback(
|
|
94
|
+
const isToday = useCallback(date => date !== null && isSameDay(date, new Date()), []);
|
|
90
95
|
const focusButton = useCallback(date => {
|
|
91
96
|
if (date === null) return;
|
|
92
97
|
const key = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
|
|
@@ -95,7 +100,7 @@ export const CalendarBody = ({
|
|
|
95
100
|
useEffect(() => {
|
|
96
101
|
if (focusTarget !== null) focusButton(focusTarget);
|
|
97
102
|
}, [focusTarget, focusButton]);
|
|
98
|
-
const handleKeyDown = useCallback((e, date) => keyHandler(e, date, onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange), [onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange]);
|
|
103
|
+
const handleKeyDown = useCallback((e, date) => keyHandler(e, date, onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange, hasAdjacentMonthRight, hasAdjacentMonthLeft), [onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange, hasAdjacentMonthLeft, hasAdjacentMonthRight]);
|
|
99
104
|
const setButtonRef = useCallback((date, el) => {
|
|
100
105
|
const k = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
|
|
101
106
|
if (el) buttonRefs.current.set(k, el);else buttonRefs.current.delete(k);
|
|
@@ -42,6 +42,10 @@ export interface CalendarBodyProps {
|
|
|
42
42
|
onVisibleDateChange: (newDate: Date) => void;
|
|
43
43
|
/** Called when the escape key is pressed */
|
|
44
44
|
onEscapeKeyPress?: () => void;
|
|
45
|
+
/** When true (e.g. two-month view), arrow keys move focus to adjacent month without changing visible date. */
|
|
46
|
+
hasAdjacentMonthRight?: boolean;
|
|
47
|
+
/** When true (e.g. two-month view), arrow keys move focus to adjacent month without changing visible date. */
|
|
48
|
+
hasAdjacentMonthLeft?: boolean;
|
|
45
49
|
}
|
|
46
50
|
export interface QuickAction {
|
|
47
51
|
num: number;
|
|
@@ -10,4 +10,4 @@ export declare const getDatesWithRow: (weeks: (Date | null)[][]) => {
|
|
|
10
10
|
export declare const keyHandler: (e: React.KeyboardEvent, date: Date, onFocusedDateChange: (date: Date | null) => void, datesWithRow: {
|
|
11
11
|
date: Date;
|
|
12
12
|
rowIndex: number;
|
|
13
|
-
}[], month: number, year: number, disabledDates: Date[], onDateSelect: (date: Date) => void, onEscapeKeyPress?: () => void, onVisibleDateChange?: ((newDate: Date) => void) | undefined) => void;
|
|
13
|
+
}[], month: number, year: number, disabledDates: Date[], onDateSelect: (date: Date) => void, onEscapeKeyPress?: () => void, onVisibleDateChange?: ((newDate: Date) => void) | undefined, hasAdjacentMonthRight?: boolean, hasAdjacentMonthLeft?: boolean) => void;
|
|
@@ -21,7 +21,7 @@ export const getDatesWithRow = weeks => {
|
|
|
21
21
|
});
|
|
22
22
|
return result;
|
|
23
23
|
};
|
|
24
|
-
export const keyHandler = (e, date, onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange) => {
|
|
24
|
+
export const keyHandler = (e, date, onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange, hasAdjacentMonthRight, hasAdjacentMonthLeft) => {
|
|
25
25
|
const key = date.getTime();
|
|
26
26
|
const idx = datesWithRow.findIndex(({
|
|
27
27
|
date: d
|
|
@@ -29,6 +29,8 @@ export const keyHandler = (e, date, onFocusedDateChange, datesWithRow, month, ye
|
|
|
29
29
|
if (idx < 0) return;
|
|
30
30
|
const currentRow = datesWithRow[idx].rowIndex;
|
|
31
31
|
const day = date.getDate();
|
|
32
|
+
const hasRight = !!hasAdjacentMonthRight;
|
|
33
|
+
const hasLeft = !!hasAdjacentMonthLeft;
|
|
32
34
|
let newDate = null;
|
|
33
35
|
let newVisibleDate = null;
|
|
34
36
|
switch (e.key) {
|
|
@@ -39,7 +41,9 @@ export const keyHandler = (e, date, onFocusedDateChange, datesWithRow, month, ye
|
|
|
39
41
|
} else {
|
|
40
42
|
const lastDayPrevMonth = new Date(year, month, 0);
|
|
41
43
|
newDate = lastDayPrevMonth;
|
|
42
|
-
|
|
44
|
+
if (!hasLeft) {
|
|
45
|
+
newVisibleDate = new Date(year, month - 1, 1);
|
|
46
|
+
}
|
|
43
47
|
}
|
|
44
48
|
break;
|
|
45
49
|
case 'ArrowRight':
|
|
@@ -48,7 +52,9 @@ export const keyHandler = (e, date, onFocusedDateChange, datesWithRow, month, ye
|
|
|
48
52
|
newDate = datesWithRow[idx + 1].date;
|
|
49
53
|
} else {
|
|
50
54
|
newDate = new Date(year, month + 1, 1);
|
|
51
|
-
|
|
55
|
+
if (!hasRight) {
|
|
56
|
+
newVisibleDate = new Date(year, month + 1, 1);
|
|
57
|
+
}
|
|
52
58
|
}
|
|
53
59
|
break;
|
|
54
60
|
case 'ArrowUp':
|
|
@@ -56,7 +62,9 @@ export const keyHandler = (e, date, onFocusedDateChange, datesWithRow, month, ye
|
|
|
56
62
|
newDate = new Date(date);
|
|
57
63
|
newDate.setDate(newDate.getDate() - 7);
|
|
58
64
|
if (newDate.getMonth() !== month || newDate.getFullYear() !== year) {
|
|
59
|
-
|
|
65
|
+
if (!hasLeft) {
|
|
66
|
+
newVisibleDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
|
|
67
|
+
}
|
|
60
68
|
}
|
|
61
69
|
break;
|
|
62
70
|
case 'ArrowDown':
|
|
@@ -64,7 +72,9 @@ export const keyHandler = (e, date, onFocusedDateChange, datesWithRow, month, ye
|
|
|
64
72
|
newDate = new Date(date);
|
|
65
73
|
newDate.setDate(newDate.getDate() + 7);
|
|
66
74
|
if (newDate.getMonth() !== month || newDate.getFullYear() !== year) {
|
|
67
|
-
|
|
75
|
+
if (!hasRight) {
|
|
76
|
+
newVisibleDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
|
|
77
|
+
}
|
|
68
78
|
}
|
|
69
79
|
break;
|
|
70
80
|
case 'Home':
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MiniArrowRightIcon } from '@codecademy/gamut-icons';
|
|
2
|
-
import { useCallback, useId,
|
|
2
|
+
import { useCallback, useId, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { FlexBox } from '../Box';
|
|
4
4
|
import { PopoverContainer } from '../PopoverContainer';
|
|
5
5
|
import { DatePickerCalendar } from './DatePickerCalendar';
|
|
@@ -30,18 +30,6 @@ export const DatePicker = props => {
|
|
|
30
30
|
const inputRef = useRef(null);
|
|
31
31
|
const dialogId = useId();
|
|
32
32
|
const calendarDialogId = `datepicker-dialog-${dialogId.replace(/:/g, '')}`;
|
|
33
|
-
const popoverOffset = 4;
|
|
34
|
-
|
|
35
|
-
// Align popover left edge with input left edge. PopoverContainer's "bottom-right"
|
|
36
|
-
// sets popover left = target left + (target width + offset + x), so we pass
|
|
37
|
-
// x = -(target width + offset) to get popover left = target left.
|
|
38
|
-
const [popoverX, setPopoverX] = useState(0);
|
|
39
|
-
useLayoutEffect(() => {
|
|
40
|
-
if (isCalendarOpen && inputRef.current) {
|
|
41
|
-
const width = inputRef.current.offsetWidth;
|
|
42
|
-
setPopoverX(-(width + popoverOffset));
|
|
43
|
-
}
|
|
44
|
-
}, [isCalendarOpen, popoverOffset]);
|
|
45
33
|
const openCalendar = useCallback(() => setIsCalendarOpen(true), []);
|
|
46
34
|
const closeCalendar = useCallback(() => {
|
|
47
35
|
setIsCalendarOpen(false);
|
|
@@ -85,14 +73,6 @@ export const DatePicker = props => {
|
|
|
85
73
|
mode: 'single'
|
|
86
74
|
};
|
|
87
75
|
}, [mode, startOrSelectedDate, endDate, setSelection, activeRangePart, setActiveRangePart, isCalendarOpen, openCalendar, closeCalendar, locale, disabledDates, calendarDialogId, translationsProp]);
|
|
88
|
-
|
|
89
|
-
// what is this doing
|
|
90
|
-
// useEffect(() => {
|
|
91
|
-
// if (!isCalendarOpen) return;
|
|
92
|
-
// const id = setTimeout(() => inputRef.current?.focus(), 0);
|
|
93
|
-
// return () => clearTimeout(id);
|
|
94
|
-
// }, [isCalendarOpen]);
|
|
95
|
-
|
|
96
76
|
const content = children !== undefined ? children : /*#__PURE__*/_jsxs(_Fragment, {
|
|
97
77
|
children: [/*#__PURE__*/_jsx(FlexBox, {
|
|
98
78
|
gap: 8,
|
|
@@ -106,7 +86,7 @@ export const DatePicker = props => {
|
|
|
106
86
|
ref: inputRef
|
|
107
87
|
}), /*#__PURE__*/_jsx(MiniArrowRightIcon, {
|
|
108
88
|
alignSelf: "center"
|
|
109
|
-
}),
|
|
89
|
+
}), /*#__PURE__*/_jsx(DatePickerInput, {
|
|
110
90
|
label: props.endLabel,
|
|
111
91
|
placeholder: placeholder,
|
|
112
92
|
rangePart: "end"
|
|
@@ -118,20 +98,20 @@ export const DatePicker = props => {
|
|
|
118
98
|
ref: inputRef
|
|
119
99
|
})
|
|
120
100
|
}), /*#__PURE__*/_jsx(PopoverContainer, {
|
|
121
|
-
alignment: "bottom-
|
|
101
|
+
alignment: "bottom-left",
|
|
122
102
|
allowPageInteraction: true,
|
|
123
103
|
focusOnProps: {
|
|
124
104
|
autoFocus: false,
|
|
125
105
|
focusLock: false
|
|
126
106
|
},
|
|
107
|
+
invertAxis: "x",
|
|
127
108
|
isOpen: isCalendarOpen,
|
|
128
|
-
offset: popoverOffset,
|
|
129
109
|
targetRef: inputRef,
|
|
130
|
-
x:
|
|
131
|
-
y:
|
|
110
|
+
x: -20,
|
|
111
|
+
y: -16,
|
|
132
112
|
onRequestClose: closeCalendar,
|
|
133
113
|
children: /*#__PURE__*/_jsx("div", {
|
|
134
|
-
"aria-label":
|
|
114
|
+
"aria-label": contextValue.translations.calendarDialogAriaLabel,
|
|
135
115
|
id: calendarDialogId,
|
|
136
116
|
role: "dialog",
|
|
137
117
|
children: /*#__PURE__*/_jsx(DatePickerCalendar, {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { breakpoints } from '@codecademy/gamut-styles';
|
|
1
2
|
import { useEffect, useId, useRef, useState } from 'react';
|
|
3
|
+
import { useMedia } from 'react-use';
|
|
2
4
|
import { Box, FlexBox } from '../Box';
|
|
3
5
|
import { Calendar, CalendarBody, CalendarFooter, CalendarHeader } from './Calendar';
|
|
4
6
|
import { useDatePicker } from './DatePickerContext';
|
|
@@ -54,7 +56,7 @@ export const DatePickerCalendar = ({
|
|
|
54
56
|
handleDateSelectSingle(date, startOrSelectedDate, setSelection);
|
|
55
57
|
} else {
|
|
56
58
|
context.setActiveRangePart(null);
|
|
57
|
-
handleDateSelectRange(date, context.activeRangePart, startOrSelectedDate, context.endDate, setSelection);
|
|
59
|
+
handleDateSelectRange(date, context.activeRangePart, startOrSelectedDate, context.endDate, setSelection, disabledDates);
|
|
58
60
|
}
|
|
59
61
|
};
|
|
60
62
|
const handleClearDate = () => {
|
|
@@ -70,6 +72,7 @@ export const DatePickerCalendar = ({
|
|
|
70
72
|
const focusTarget = focusedDate ?? startOrSelectedDate ?? endDate ?? new Date();
|
|
71
73
|
const addMonths = (date, n) => new Date(date.getFullYear(), date.getMonth() + n, 1);
|
|
72
74
|
const secondMonthDate = addMonths(visibleDate, 1);
|
|
75
|
+
const isTwoMonthsVisible = useMedia(`(min-width: ${breakpoints.xs})`);
|
|
73
76
|
return /*#__PURE__*/_jsxs(Calendar, {
|
|
74
77
|
children: [/*#__PURE__*/_jsxs(Box, {
|
|
75
78
|
p: 24,
|
|
@@ -84,6 +87,7 @@ export const DatePickerCalendar = ({
|
|
|
84
87
|
disabledDates: disabledDates,
|
|
85
88
|
endDate: endDate,
|
|
86
89
|
focusedDate: focusTarget,
|
|
90
|
+
hasAdjacentMonthRight: isTwoMonthsVisible,
|
|
87
91
|
labelledById: headingId,
|
|
88
92
|
locale: locale,
|
|
89
93
|
selectedDate: startOrSelectedDate,
|
|
@@ -106,6 +110,7 @@ export const DatePickerCalendar = ({
|
|
|
106
110
|
disabledDates: disabledDates,
|
|
107
111
|
endDate: endDate,
|
|
108
112
|
focusedDate: focusTarget,
|
|
113
|
+
hasAdjacentMonthLeft: isTwoMonthsVisible,
|
|
109
114
|
labelledById: headingId,
|
|
110
115
|
locale: locale,
|
|
111
116
|
selectedDate: startOrSelectedDate,
|
|
@@ -119,7 +124,7 @@ export const DatePickerCalendar = ({
|
|
|
119
124
|
})]
|
|
120
125
|
})]
|
|
121
126
|
}), /*#__PURE__*/_jsx(CalendarFooter, {
|
|
122
|
-
clearText: translations.
|
|
127
|
+
clearText: translations.clearText,
|
|
123
128
|
disabled: startOrSelectedDate === null && endDate === null,
|
|
124
129
|
locale: locale,
|
|
125
130
|
showClearButton: isRange,
|
|
@@ -44,7 +44,8 @@ export const DatePickerInput = /*#__PURE__*/forwardRef(({
|
|
|
44
44
|
openCalendar,
|
|
45
45
|
locale,
|
|
46
46
|
isCalendarOpen,
|
|
47
|
-
calendarDialogId
|
|
47
|
+
calendarDialogId,
|
|
48
|
+
translations
|
|
48
49
|
} = context;
|
|
49
50
|
const isRange = mode === 'range';
|
|
50
51
|
const inputID = useId();
|
|
@@ -98,12 +99,13 @@ export const DatePickerInput = /*#__PURE__*/forwardRef(({
|
|
|
98
99
|
const handleOpenCalendar = () => {
|
|
99
100
|
openCalendar();
|
|
100
101
|
};
|
|
101
|
-
const defaultLabel = isRange
|
|
102
|
+
const defaultLabel = !isRange ? translations.dateLabel : rangePart === 'end' ? translations.endDateLabel : translations.startDateLabel;
|
|
102
103
|
return /*#__PURE__*/_jsx(FormGroup, {
|
|
103
104
|
htmlFor: inputId,
|
|
104
105
|
isSoloField: true // should probaly be based on a prop
|
|
105
106
|
,
|
|
106
107
|
label: label ?? defaultLabel,
|
|
108
|
+
mb: 0,
|
|
107
109
|
pb: 0,
|
|
108
110
|
spacing: "tight",
|
|
109
111
|
width: "170px",
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
/** Default UI strings; pass translations prop to override. */
|
|
2
2
|
export const DEFAULT_DATE_PICKER_TRANSLATIONS = {
|
|
3
|
-
|
|
3
|
+
clearText: 'Clear',
|
|
4
|
+
dateLabel: 'Date',
|
|
5
|
+
startDateLabel: 'Start date',
|
|
6
|
+
endDateLabel: 'End date',
|
|
7
|
+
calendarDialogAriaLabel: 'Choose date'
|
|
4
8
|
};
|
|
@@ -53,7 +53,15 @@ export type ActiveRangePart = 'start' | 'end' | null;
|
|
|
53
53
|
/** Optional translations for DatePicker UI strings. Pass to override defaults. */
|
|
54
54
|
export interface DatePickerTranslations {
|
|
55
55
|
/** Label for the clear date button (default: "Clear"). */
|
|
56
|
-
|
|
56
|
+
clearText?: string;
|
|
57
|
+
/** Default label for the date input in single mode (default: "Date"). */
|
|
58
|
+
dateLabel?: string;
|
|
59
|
+
/** Default label for the start date input in range mode (default: "Start date"). */
|
|
60
|
+
startDateLabel?: string;
|
|
61
|
+
/** Default label for the end date input in range mode (default: "End date"). */
|
|
62
|
+
endDateLabel?: string;
|
|
63
|
+
/** aria-label for the calendar dialog (default: "Choose date"). */
|
|
64
|
+
calendarDialogAriaLabel?: string;
|
|
57
65
|
}
|
|
58
66
|
/** Shared state provided by DatePicker via context. */
|
|
59
67
|
export interface DatePickerBaseContextValue {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { ActiveRangePart } from './types';
|
|
2
|
+
/** True if any disabled date falls within [start, end] (inclusive, by calendar day). */
|
|
3
|
+
export declare const rangeContainsDisabled: (start: Date, end: Date, disabledDates: Date[]) => boolean;
|
|
2
4
|
export declare const handleDateSelectSingle: (date: Date, selectedDate: Date | null, setSelection: (date: Date | null) => void) => void;
|
|
3
|
-
export declare const handleDateSelectRange: (date: Date, activeRangePart: ActiveRangePart, startDate: Date | null, endDate: Date | null, setSelection: (startDate: Date | null, endDate?: Date | null) => void) => void;
|
|
5
|
+
export declare const handleDateSelectRange: (date: Date, activeRangePart: ActiveRangePart, startDate: Date | null, endDate: Date | null, setSelection: (startDate: Date | null, endDate?: Date | null) => void, disabledDates: Date[]) => void;
|
package/dist/DatePicker/utils.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { isDateInRange, isSameDay } from './Calendar/utils/dateGrid';
|
|
2
|
+
/** True if any disabled date falls within [start, end] (inclusive, by calendar day). */
|
|
3
|
+
export const rangeContainsDisabled = (start, end, disabledDates) => {
|
|
4
|
+
return disabledDates.some(date => isSameDay(date, start) || isSameDay(date, end) || isDateInRange(date, start, end));
|
|
5
|
+
};
|
|
1
6
|
export const handleDateSelectSingle = (date, selectedDate, setSelection) => {
|
|
2
7
|
// If clicked date is the same as Start Date: Clear Start Date
|
|
3
8
|
if (selectedDate && date.getTime() === selectedDate.getTime()) {
|
|
@@ -7,7 +12,15 @@ export const handleDateSelectSingle = (date, selectedDate, setSelection) => {
|
|
|
7
12
|
// If clicked date is not the same as Start Date: Set Start Date to clicked date
|
|
8
13
|
setSelection(date);
|
|
9
14
|
};
|
|
10
|
-
|
|
15
|
+
const applyRangeOrNewStart = (start, end, clickedDate, disabledDates, setSelection) => {
|
|
16
|
+
// if range contains disabled dates, set start date to clicked date and end date to null
|
|
17
|
+
if (rangeContainsDisabled(start, end, disabledDates)) {
|
|
18
|
+
setSelection(clickedDate, null);
|
|
19
|
+
} else {
|
|
20
|
+
setSelection(start, end);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export const handleDateSelectRange = (date, activeRangePart, startDate, endDate, setSelection, disabledDates) => {
|
|
11
24
|
// Range mode: field targeting (start or end input was focused)
|
|
12
25
|
if (activeRangePart === 'start') {
|
|
13
26
|
if (date.getTime() === startDate?.getTime()) {
|
|
@@ -15,7 +28,11 @@ export const handleDateSelectRange = (date, activeRangePart, startDate, endDate,
|
|
|
15
28
|
return;
|
|
16
29
|
}
|
|
17
30
|
const newEnd = endDate != null && date.getTime() <= endDate.getTime() ? endDate : null;
|
|
18
|
-
|
|
31
|
+
if (newEnd != null) {
|
|
32
|
+
applyRangeOrNewStart(date, newEnd, date, disabledDates, setSelection);
|
|
33
|
+
} else {
|
|
34
|
+
setSelection(date, newEnd);
|
|
35
|
+
}
|
|
19
36
|
return;
|
|
20
37
|
}
|
|
21
38
|
if (activeRangePart === 'end') {
|
|
@@ -24,7 +41,11 @@ export const handleDateSelectRange = (date, activeRangePart, startDate, endDate,
|
|
|
24
41
|
return;
|
|
25
42
|
}
|
|
26
43
|
const newStart = startDate != null && date.getTime() >= startDate.getTime() ? startDate : null;
|
|
27
|
-
|
|
44
|
+
if (newStart != null) {
|
|
45
|
+
applyRangeOrNewStart(newStart, date, date, disabledDates, setSelection);
|
|
46
|
+
} else {
|
|
47
|
+
setSelection(newStart, date);
|
|
48
|
+
}
|
|
28
49
|
return;
|
|
29
50
|
}
|
|
30
51
|
|
|
@@ -47,12 +68,11 @@ export const handleDateSelectRange = (date, activeRangePart, startDate, endDate,
|
|
|
47
68
|
}
|
|
48
69
|
// If clicked date > Start: Updates End Date to new date (Start remains)
|
|
49
70
|
if (date.getTime() > startDate.getTime()) {
|
|
50
|
-
|
|
71
|
+
applyRangeOrNewStart(startDate, date, date, disabledDates, setSelection);
|
|
51
72
|
return;
|
|
52
73
|
}
|
|
53
74
|
// If clicked date < Start: Updates Start Date to new date (End remains) - extends range to the left
|
|
54
|
-
|
|
55
|
-
setSelection(date, endDate);
|
|
75
|
+
applyRangeOrNewStart(date, endDate, date, disabledDates, setSelection);
|
|
56
76
|
return;
|
|
57
77
|
}
|
|
58
78
|
// Start is Set, End is Empty
|
|
@@ -60,10 +80,9 @@ export const handleDateSelectRange = (date, activeRangePart, startDate, endDate,
|
|
|
60
80
|
// If clicked date < Start: Restarts selection with clicked date as new Start
|
|
61
81
|
if (date.getTime() < startDate.getTime()) {
|
|
62
82
|
setSelection(date, null);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
setSelection(startDate, date);
|
|
83
|
+
} else {
|
|
84
|
+
// If clicked date > Start: Sets it as End Date (if range valid)
|
|
85
|
+
applyRangeOrNewStart(startDate, date, date, disabledDates, setSelection);
|
|
67
86
|
}
|
|
68
87
|
return;
|
|
69
88
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codecademy/gamut",
|
|
3
3
|
"description": "Styleguide & Component library for Codecademy",
|
|
4
|
-
"version": "68.1.3-alpha.
|
|
4
|
+
"version": "68.1.3-alpha.9e4fc9.0",
|
|
5
5
|
"author": "Codecademy Engineering <dev@codecademy.com>",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@codecademy/gamut-icons": "9.57.0",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"dist/**/[A-Z]**/[A-Z]*.js",
|
|
60
60
|
"dist/**/[A-Z]**/index.js"
|
|
61
61
|
],
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "8c03a3442dcceebd8c605dcd82d04d0edad5e3a9"
|
|
63
63
|
}
|