@codecademy/gamut 68.2.3-alpha.df22d8.0 → 68.2.3-alpha.e0ecfc.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.
Files changed (62) hide show
  1. package/dist/DatePicker/Calendar/CalendarBody.d.ts +3 -0
  2. package/dist/DatePicker/Calendar/CalendarBody.js +143 -0
  3. package/dist/DatePicker/Calendar/CalendarFooter.d.ts +3 -0
  4. package/dist/DatePicker/Calendar/CalendarFooter.js +57 -0
  5. package/dist/DatePicker/Calendar/CalendarHeader.d.ts +3 -0
  6. package/dist/DatePicker/Calendar/CalendarHeader.js +46 -0
  7. package/dist/DatePicker/Calendar/CalendarNavLastMonth.d.ts +3 -0
  8. package/dist/DatePicker/Calendar/CalendarNavLastMonth.js +30 -0
  9. package/dist/DatePicker/Calendar/CalendarNavNextMonth.d.ts +3 -0
  10. package/dist/DatePicker/Calendar/CalendarNavNextMonth.js +30 -0
  11. package/dist/DatePicker/Calendar/CalendarWrapper.d.ts +8 -0
  12. package/dist/DatePicker/Calendar/CalendarWrapper.js +27 -0
  13. package/dist/DatePicker/Calendar/index.d.ts +6 -0
  14. package/dist/DatePicker/Calendar/index.js +6 -0
  15. package/dist/DatePicker/Calendar/types.d.ts +77 -0
  16. package/dist/DatePicker/Calendar/types.js +1 -0
  17. package/dist/DatePicker/Calendar/utils/dateGrid.d.ts +38 -0
  18. package/dist/DatePicker/Calendar/utils/dateGrid.js +103 -0
  19. package/dist/DatePicker/Calendar/utils/elements.d.ts +18 -0
  20. package/dist/DatePicker/Calendar/utils/elements.js +116 -0
  21. package/dist/DatePicker/Calendar/utils/format.d.ts +28 -0
  22. package/dist/DatePicker/Calendar/utils/format.js +72 -0
  23. package/dist/DatePicker/Calendar/utils/keyHandler.d.ts +12 -0
  24. package/dist/DatePicker/Calendar/utils/keyHandler.js +126 -0
  25. package/dist/DatePicker/Calendar/utils/validation.d.ts +13 -0
  26. package/dist/DatePicker/Calendar/utils/validation.js +23 -0
  27. package/dist/DatePicker/DatePicker.d.ts +7 -0
  28. package/dist/DatePicker/DatePicker.js +157 -0
  29. package/dist/DatePicker/DatePickerCalendar.d.ts +11 -0
  30. package/dist/DatePicker/DatePickerCalendar.js +163 -0
  31. package/dist/DatePicker/DatePickerContext.d.ts +10 -0
  32. package/dist/DatePicker/DatePickerContext.js +18 -0
  33. package/dist/DatePicker/DatePickerInput/Segment/DatePickerInputSegment.d.ts +20 -0
  34. package/dist/DatePicker/DatePickerInput/Segment/DatePickerInputSegment.js +138 -0
  35. package/dist/DatePicker/DatePickerInput/Segment/elements.d.ts +16 -0
  36. package/dist/DatePicker/DatePickerInput/Segment/elements.js +34 -0
  37. package/dist/DatePicker/DatePickerInput/Segment/index.d.ts +4 -0
  38. package/dist/DatePicker/DatePickerInput/Segment/index.js +3 -0
  39. package/dist/DatePicker/DatePickerInput/Segment/segmentUtils.d.ts +49 -0
  40. package/dist/DatePicker/DatePickerInput/Segment/segmentUtils.js +202 -0
  41. package/dist/DatePicker/DatePickerInput/elements.d.ts +15 -0
  42. package/dist/DatePicker/DatePickerInput/elements.js +19 -0
  43. package/dist/DatePicker/DatePickerInput/index.d.ts +13 -0
  44. package/dist/DatePicker/DatePickerInput/index.js +187 -0
  45. package/dist/DatePicker/DatePickerInput/utils.d.ts +17 -0
  46. package/dist/DatePicker/DatePickerInput/utils.js +50 -0
  47. package/dist/DatePicker/index.d.ts +5 -0
  48. package/dist/DatePicker/index.js +5 -0
  49. package/dist/DatePicker/types.d.ts +86 -0
  50. package/dist/DatePicker/types.js +1 -0
  51. package/dist/DatePicker/utils/dateSelect.d.ts +19 -0
  52. package/dist/DatePicker/utils/dateSelect.js +146 -0
  53. package/dist/DatePicker/utils/locale.d.ts +38 -0
  54. package/dist/DatePicker/utils/locale.js +93 -0
  55. package/dist/DatePicker/utils/translations.d.ts +15 -0
  56. package/dist/DatePicker/utils/translations.js +10 -0
  57. package/dist/FocusTrap/index.d.ts +2 -2
  58. package/dist/PopoverContainer/PopoverContainer.js +23 -3
  59. package/dist/PopoverContainer/types.d.ts +5 -0
  60. package/dist/index.d.ts +2 -0
  61. package/dist/index.js +2 -0
  62. package/package.json +7 -6
@@ -0,0 +1,116 @@
1
+ import _styled from "@emotion/styled/base";
2
+ import { css, states, transitionConcat } from '@codecademy/gamut-styles';
3
+ export const CalendarTable = /*#__PURE__*/_styled("table", {
4
+ target: "eyan6kk2",
5
+ label: "CalendarTable"
6
+ })(css({
7
+ /** Row gaps only: 0 between columns, 8px token between rows (incl. under header). */
8
+ borderCollapse: 'separate',
9
+ borderSpacing: '0 8px'
10
+ }), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL3V0aWxzL2VsZW1lbnRzLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJNkIiLCJmaWxlIjoiLi4vLi4vLi4vLi4vc3JjL0RhdGVQaWNrZXIvQ2FsZW5kYXIvdXRpbHMvZWxlbWVudHMudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBzdGF0ZXMsIHRyYW5zaXRpb25Db25jYXQgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHsgU3R5bGVQcm9wcyB9IGZyb20gJ0Bjb2RlY2FkZW15L3ZhcmlhbmNlJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJztcblxuZXhwb3J0IGNvbnN0IENhbGVuZGFyVGFibGUgPSBzdHlsZWQudGFibGUoXG4gIGNzcyh7XG4gICAgLyoqIFJvdyBnYXBzIG9ubHk6IDAgYmV0d2VlbiBjb2x1bW5zLCA4cHggdG9rZW4gYmV0d2VlbiByb3dzIChpbmNsLiB1bmRlciBoZWFkZXIpLiAqL1xuICAgIGJvcmRlckNvbGxhcHNlOiAnc2VwYXJhdGUnLFxuICAgIGJvcmRlclNwYWNpbmc6ICcwIDhweCcsXG4gIH0pXG4pO1xuXG5leHBvcnQgY29uc3QgVGFibGVIZWFkZXIgPSBzdHlsZWQudGgoXG4gIGNzcyh7XG4gICAgZm9udFNpemU6IDE0LFxuICAgIGZvbnRXZWlnaHQ6ICdiYXNlJyxcbiAgICBjb2xvcjogJ3RleHQtZGlzYWJsZWQnLFxuICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG4gIH0pXG4pO1xuXG5jb25zdCBkYXRlY2VsbFN0YXRlcyA9IHN0YXRlcyh7XG4gIGlzVG9kYXk6IHtcbiAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICBjb250ZW50OiAnXCJcIicsXG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIGJvdHRvbTogNCxcbiAgICAgIC8vIEhhbGYgb2YgZG90IHdpZHRoICg0cHgpIHNvIHRoZSBtYXJrZXIgc2l0cyB1bmRlciB0aGUgY2VudGVyZWQgZGF0ZSBudW1lcmFsLlxuICAgICAgaW5zZXRJbmxpbmVTdGFydDogJ2NhbGMoNTAlIC0gMnB4KScsXG4gICAgICB3aWR0aDogNCxcbiAgICAgIGhlaWdodDogNCxcbiAgICAgIGJvcmRlclJhZGl1czogJ2Z1bGwnLFxuICAgICAgYmc6ICdoeXBlcicsXG4gICAgfSxcbiAgfSxcbiAgaXNTZWxlY3RlZDoge1xuICAgIGJnOiAndGV4dCcsXG4gICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAnJjpob3ZlciwgJjpmb2N1cyc6IHtcbiAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgIGNvbG9yOiAnYmFja2dyb3VuZCcsXG4gICAgfSxcbiAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICBiZzogJ2JhY2tncm91bmQnLFxuICAgIH0sXG4gIH0sXG4gIGlzUmFuZ2VTdGFydDoge1xuICAgIGJvcmRlclJhZGl1c1JpZ2h0OiAnbm9uZScsXG4gIH0sXG4gIGlzUmFuZ2VFbmQ6IHtcbiAgICBib3JkZXJSYWRpdXNMZWZ0OiAnbm9uZScsXG4gIH0sXG4gIGlzSW5SYW5nZToge1xuICAgIGJnOiAndGV4dC1kaXNhYmxlZCcsXG4gICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICBib3JkZXJSYWRpdXM6ICdub25lJyxcbiAgICAnJjpob3ZlciwgJjpmb2N1cyc6IHtcbiAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgIGNvbG9yOiAnYmFja2dyb3VuZCcsXG4gICAgfSxcbiAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICBiZzogJ2JhY2tncm91bmQnLFxuICAgIH0sXG4gIH0sXG4gIGlzRGlzYWJsZWQ6IHtcbiAgICBjb2xvcjogJ3RleHQtZGlzYWJsZWQnLFxuICAgIGJnOiAndHJhbnNwYXJlbnQnLFxuICAgIGN1cnNvcjogJ25vdC1hbGxvd2VkJyxcbiAgICB1c2VyU2VsZWN0OiAnbm9uZScsXG4gICAgdGV4dERlY29yYXRpb246ICdsaW5lLXRocm91Z2gnLFxuICAgICcmOmhvdmVyJzoge1xuICAgICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICAgIGJnOiAndHJhbnNwYXJlbnQnLFxuICAgICAgdGV4dERlY29yYXRpb246ICdsaW5lLXRocm91Z2gnLFxuICAgICAgY3Vyc29yOiAnbm90LWFsbG93ZWQnLFxuICAgICAgdXNlclNlbGVjdDogJ25vbmUnLFxuICAgIH0sXG4gIH0sXG59KTtcblxudHlwZSBEYXRlQ2VsbFByb3BzID0gU3R5bGVQcm9wczx0eXBlb2YgZGF0ZWNlbGxTdGF0ZXM+O1xuXG5leHBvcnQgY29uc3QgRGF0ZUNlbGwgPSBzdHlsZWQudGQ8RGF0ZUNlbGxQcm9wcz4oXG4gIGNzcyh7XG4gICAgZm9udFdlaWdodDogJ2Jhc2UnLFxuICAgIHdpZHRoOiAnMzJweCcsXG4gICAgaGVpZ2h0OiAnMzJweCcsXG4gICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICBwYWRkaW5nOiAwLFxuICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuICAgIGJvcmRlclJhZGl1czogJ21kJyxcbiAgICB0cmFuc2l0aW9uOiB0cmFuc2l0aW9uQ29uY2F0KFxuICAgICAgWydib3JkZXItY29sb3InLCAnY29sb3InLCAnYmFja2dyb3VuZC1jb2xvcicsICdib3gtc2hhZG93J10sXG4gICAgICAnZmFzdCcsXG4gICAgICAnZWFzZS1pbidcbiAgICApLFxuICAgICcmOmhvdmVyJzoge1xuICAgICAgY29sb3I6ICdzZWNvbmRhcnknLFxuICAgICAgYmc6ICdiYWNrZ3JvdW5kLWhvdmVyJyxcbiAgICAgIHRyYW5zaXRpb246IHRyYW5zaXRpb25Db25jYXQoXG4gICAgICAgIFsnYmFja2dyb3VuZC1jb2xvcicsICdib3gtc2hhZG93J10sXG4gICAgICAgICdmYXN0JyxcbiAgICAgICAgJ2Vhc2UtaW4nXG4gICAgICApLFxuICAgICAgY3Vyc29yOiAncG9pbnRlcicsXG4gICAgfSxcbiAgICAnJjpmb2N1cy12aXNpYmxlJzoge1xuICAgICAgY29sb3I6ICdzZWNvbmRhcnknLFxuICAgICAgb3V0bGluZTogJ25vbmUnLFxuICAgIH0sXG4gICAgJyY6YWN0aXZlJzoge1xuICAgICAgY29sb3I6ICd0ZXh0JyxcbiAgICB9LFxuICAgICcmOjpiZWZvcmUnOiB7XG4gICAgICBjb250ZW50OiAnXCJcIicsXG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIGluc2V0OiAtMyxcbiAgICAgIGJvcmRlclJhZGl1czogJ2xnJyxcbiAgICAgIGJvcmRlcjogMixcbiAgICAgIG9wYWNpdHk6IDAsXG4gICAgICB6SW5kZXg6IDAsXG4gICAgfSxcbiAgICAnJjpmb2N1cy12aXNpYmxlOjpiZWZvcmUnOiB7XG4gICAgICBvcGFjaXR5OiAxLFxuICAgIH0sXG4gIH0pLFxuICBkYXRlY2VsbFN0YXRlc1xuKTtcbiJdfQ== */");
11
+ export const TableHeader = /*#__PURE__*/_styled("th", {
12
+ target: "eyan6kk1",
13
+ label: "TableHeader"
14
+ })(css({
15
+ fontSize: 14,
16
+ fontWeight: 'base',
17
+ color: 'text-disabled',
18
+ textAlign: 'center'
19
+ }), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL3V0aWxzL2VsZW1lbnRzLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFZMkIiLCJmaWxlIjoiLi4vLi4vLi4vLi4vc3JjL0RhdGVQaWNrZXIvQ2FsZW5kYXIvdXRpbHMvZWxlbWVudHMudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBzdGF0ZXMsIHRyYW5zaXRpb25Db25jYXQgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHsgU3R5bGVQcm9wcyB9IGZyb20gJ0Bjb2RlY2FkZW15L3ZhcmlhbmNlJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJztcblxuZXhwb3J0IGNvbnN0IENhbGVuZGFyVGFibGUgPSBzdHlsZWQudGFibGUoXG4gIGNzcyh7XG4gICAgLyoqIFJvdyBnYXBzIG9ubHk6IDAgYmV0d2VlbiBjb2x1bW5zLCA4cHggdG9rZW4gYmV0d2VlbiByb3dzIChpbmNsLiB1bmRlciBoZWFkZXIpLiAqL1xuICAgIGJvcmRlckNvbGxhcHNlOiAnc2VwYXJhdGUnLFxuICAgIGJvcmRlclNwYWNpbmc6ICcwIDhweCcsXG4gIH0pXG4pO1xuXG5leHBvcnQgY29uc3QgVGFibGVIZWFkZXIgPSBzdHlsZWQudGgoXG4gIGNzcyh7XG4gICAgZm9udFNpemU6IDE0LFxuICAgIGZvbnRXZWlnaHQ6ICdiYXNlJyxcbiAgICBjb2xvcjogJ3RleHQtZGlzYWJsZWQnLFxuICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG4gIH0pXG4pO1xuXG5jb25zdCBkYXRlY2VsbFN0YXRlcyA9IHN0YXRlcyh7XG4gIGlzVG9kYXk6IHtcbiAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICBjb250ZW50OiAnXCJcIicsXG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIGJvdHRvbTogNCxcbiAgICAgIC8vIEhhbGYgb2YgZG90IHdpZHRoICg0cHgpIHNvIHRoZSBtYXJrZXIgc2l0cyB1bmRlciB0aGUgY2VudGVyZWQgZGF0ZSBudW1lcmFsLlxuICAgICAgaW5zZXRJbmxpbmVTdGFydDogJ2NhbGMoNTAlIC0gMnB4KScsXG4gICAgICB3aWR0aDogNCxcbiAgICAgIGhlaWdodDogNCxcbiAgICAgIGJvcmRlclJhZGl1czogJ2Z1bGwnLFxuICAgICAgYmc6ICdoeXBlcicsXG4gICAgfSxcbiAgfSxcbiAgaXNTZWxlY3RlZDoge1xuICAgIGJnOiAndGV4dCcsXG4gICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAnJjpob3ZlciwgJjpmb2N1cyc6IHtcbiAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgIGNvbG9yOiAnYmFja2dyb3VuZCcsXG4gICAgfSxcbiAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICBiZzogJ2JhY2tncm91bmQnLFxuICAgIH0sXG4gIH0sXG4gIGlzUmFuZ2VTdGFydDoge1xuICAgIGJvcmRlclJhZGl1c1JpZ2h0OiAnbm9uZScsXG4gIH0sXG4gIGlzUmFuZ2VFbmQ6IHtcbiAgICBib3JkZXJSYWRpdXNMZWZ0OiAnbm9uZScsXG4gIH0sXG4gIGlzSW5SYW5nZToge1xuICAgIGJnOiAndGV4dC1kaXNhYmxlZCcsXG4gICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICBib3JkZXJSYWRpdXM6ICdub25lJyxcbiAgICAnJjpob3ZlciwgJjpmb2N1cyc6IHtcbiAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgIGNvbG9yOiAnYmFja2dyb3VuZCcsXG4gICAgfSxcbiAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICBiZzogJ2JhY2tncm91bmQnLFxuICAgIH0sXG4gIH0sXG4gIGlzRGlzYWJsZWQ6IHtcbiAgICBjb2xvcjogJ3RleHQtZGlzYWJsZWQnLFxuICAgIGJnOiAndHJhbnNwYXJlbnQnLFxuICAgIGN1cnNvcjogJ25vdC1hbGxvd2VkJyxcbiAgICB1c2VyU2VsZWN0OiAnbm9uZScsXG4gICAgdGV4dERlY29yYXRpb246ICdsaW5lLXRocm91Z2gnLFxuICAgICcmOmhvdmVyJzoge1xuICAgICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICAgIGJnOiAndHJhbnNwYXJlbnQnLFxuICAgICAgdGV4dERlY29yYXRpb246ICdsaW5lLXRocm91Z2gnLFxuICAgICAgY3Vyc29yOiAnbm90LWFsbG93ZWQnLFxuICAgICAgdXNlclNlbGVjdDogJ25vbmUnLFxuICAgIH0sXG4gIH0sXG59KTtcblxudHlwZSBEYXRlQ2VsbFByb3BzID0gU3R5bGVQcm9wczx0eXBlb2YgZGF0ZWNlbGxTdGF0ZXM+O1xuXG5leHBvcnQgY29uc3QgRGF0ZUNlbGwgPSBzdHlsZWQudGQ8RGF0ZUNlbGxQcm9wcz4oXG4gIGNzcyh7XG4gICAgZm9udFdlaWdodDogJ2Jhc2UnLFxuICAgIHdpZHRoOiAnMzJweCcsXG4gICAgaGVpZ2h0OiAnMzJweCcsXG4gICAgdGV4dEFsaWduOiAnY2VudGVyJyxcbiAgICBwYWRkaW5nOiAwLFxuICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuICAgIGJvcmRlclJhZGl1czogJ21kJyxcbiAgICB0cmFuc2l0aW9uOiB0cmFuc2l0aW9uQ29uY2F0KFxuICAgICAgWydib3JkZXItY29sb3InLCAnY29sb3InLCAnYmFja2dyb3VuZC1jb2xvcicsICdib3gtc2hhZG93J10sXG4gICAgICAnZmFzdCcsXG4gICAgICAnZWFzZS1pbidcbiAgICApLFxuICAgICcmOmhvdmVyJzoge1xuICAgICAgY29sb3I6ICdzZWNvbmRhcnknLFxuICAgICAgYmc6ICdiYWNrZ3JvdW5kLWhvdmVyJyxcbiAgICAgIHRyYW5zaXRpb246IHRyYW5zaXRpb25Db25jYXQoXG4gICAgICAgIFsnYmFja2dyb3VuZC1jb2xvcicsICdib3gtc2hhZG93J10sXG4gICAgICAgICdmYXN0JyxcbiAgICAgICAgJ2Vhc2UtaW4nXG4gICAgICApLFxuICAgICAgY3Vyc29yOiAncG9pbnRlcicsXG4gICAgfSxcbiAgICAnJjpmb2N1cy12aXNpYmxlJzoge1xuICAgICAgY29sb3I6ICdzZWNvbmRhcnknLFxuICAgICAgb3V0bGluZTogJ25vbmUnLFxuICAgIH0sXG4gICAgJyY6YWN0aXZlJzoge1xuICAgICAgY29sb3I6ICd0ZXh0JyxcbiAgICB9LFxuICAgICcmOjpiZWZvcmUnOiB7XG4gICAgICBjb250ZW50OiAnXCJcIicsXG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIGluc2V0OiAtMyxcbiAgICAgIGJvcmRlclJhZGl1czogJ2xnJyxcbiAgICAgIGJvcmRlcjogMixcbiAgICAgIG9wYWNpdHk6IDAsXG4gICAgICB6SW5kZXg6IDAsXG4gICAgfSxcbiAgICAnJjpmb2N1cy12aXNpYmxlOjpiZWZvcmUnOiB7XG4gICAgICBvcGFjaXR5OiAxLFxuICAgIH0sXG4gIH0pLFxuICBkYXRlY2VsbFN0YXRlc1xuKTtcbiJdfQ== */");
20
+ const datecellStates = states({
21
+ isToday: {
22
+ position: 'relative',
23
+ '&::after': {
24
+ content: '""',
25
+ position: 'absolute',
26
+ bottom: 4,
27
+ // Half of dot width (4px) so the marker sits under the centered date numeral.
28
+ insetInlineStart: 'calc(50% - 2px)',
29
+ width: 4,
30
+ height: 4,
31
+ borderRadius: 'full',
32
+ bg: 'hyper'
33
+ }
34
+ },
35
+ isSelected: {
36
+ bg: 'text',
37
+ color: 'background',
38
+ '&:hover, &:focus': {
39
+ bg: 'secondary-hover',
40
+ color: 'background'
41
+ },
42
+ '&::after': {
43
+ bg: 'background'
44
+ }
45
+ },
46
+ isRangeStart: {
47
+ borderRadiusRight: 'none'
48
+ },
49
+ isRangeEnd: {
50
+ borderRadiusLeft: 'none'
51
+ },
52
+ isInRange: {
53
+ bg: 'text-disabled',
54
+ color: 'background',
55
+ borderRadius: 'none',
56
+ '&:hover, &:focus': {
57
+ bg: 'secondary-hover',
58
+ color: 'background'
59
+ },
60
+ '&::after': {
61
+ bg: 'background'
62
+ }
63
+ },
64
+ isDisabled: {
65
+ color: 'text-disabled',
66
+ bg: 'transparent',
67
+ cursor: 'not-allowed',
68
+ userSelect: 'none',
69
+ textDecoration: 'line-through',
70
+ '&:hover': {
71
+ color: 'text-disabled',
72
+ bg: 'transparent',
73
+ textDecoration: 'line-through',
74
+ cursor: 'not-allowed',
75
+ userSelect: 'none'
76
+ }
77
+ }
78
+ });
79
+ export const DateCell = /*#__PURE__*/_styled("td", {
80
+ target: "eyan6kk0",
81
+ label: "DateCell"
82
+ })(css({
83
+ fontWeight: 'base',
84
+ width: '32px',
85
+ height: '32px',
86
+ textAlign: 'center',
87
+ padding: 0,
88
+ position: 'relative',
89
+ borderRadius: 'md',
90
+ transition: transitionConcat(['border-color', 'color', 'background-color', 'box-shadow'], 'fast', 'ease-in'),
91
+ '&:hover': {
92
+ color: 'secondary',
93
+ bg: 'background-hover',
94
+ transition: transitionConcat(['background-color', 'box-shadow'], 'fast', 'ease-in'),
95
+ cursor: 'pointer'
96
+ },
97
+ '&:focus-visible': {
98
+ color: 'secondary',
99
+ outline: 'none'
100
+ },
101
+ '&:active': {
102
+ color: 'text'
103
+ },
104
+ '&::before': {
105
+ content: '""',
106
+ position: 'absolute',
107
+ inset: -3,
108
+ borderRadius: 'lg',
109
+ border: 2,
110
+ opacity: 0,
111
+ zIndex: 0
112
+ },
113
+ '&:focus-visible::before': {
114
+ opacity: 1
115
+ }
116
+ }), datecellStates, process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL3V0aWxzL2VsZW1lbnRzLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFtRndCIiwiZmlsZSI6Ii4uLy4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL3V0aWxzL2VsZW1lbnRzLnRzeCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcywgc3RhdGVzLCB0cmFuc2l0aW9uQ29uY2F0IH0gZnJvbSAnQGNvZGVjYWRlbXkvZ2FtdXQtc3R5bGVzJztcbmltcG9ydCB7IFN0eWxlUHJvcHMgfSBmcm9tICdAY29kZWNhZGVteS92YXJpYW5jZSc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5cbmV4cG9ydCBjb25zdCBDYWxlbmRhclRhYmxlID0gc3R5bGVkLnRhYmxlKFxuICBjc3Moe1xuICAgIC8qKiBSb3cgZ2FwcyBvbmx5OiAwIGJldHdlZW4gY29sdW1ucywgOHB4IHRva2VuIGJldHdlZW4gcm93cyAoaW5jbC4gdW5kZXIgaGVhZGVyKS4gKi9cbiAgICBib3JkZXJDb2xsYXBzZTogJ3NlcGFyYXRlJyxcbiAgICBib3JkZXJTcGFjaW5nOiAnMCA4cHgnLFxuICB9KVxuKTtcblxuZXhwb3J0IGNvbnN0IFRhYmxlSGVhZGVyID0gc3R5bGVkLnRoKFxuICBjc3Moe1xuICAgIGZvbnRTaXplOiAxNCxcbiAgICBmb250V2VpZ2h0OiAnYmFzZScsXG4gICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICB9KVxuKTtcblxuY29uc3QgZGF0ZWNlbGxTdGF0ZXMgPSBzdGF0ZXMoe1xuICBpc1RvZGF5OiB7XG4gICAgcG9zaXRpb246ICdyZWxhdGl2ZScsXG4gICAgJyY6OmFmdGVyJzoge1xuICAgICAgY29udGVudDogJ1wiXCInLFxuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICBib3R0b206IDQsXG4gICAgICAvLyBIYWxmIG9mIGRvdCB3aWR0aCAoNHB4KSBzbyB0aGUgbWFya2VyIHNpdHMgdW5kZXIgdGhlIGNlbnRlcmVkIGRhdGUgbnVtZXJhbC5cbiAgICAgIGluc2V0SW5saW5lU3RhcnQ6ICdjYWxjKDUwJSAtIDJweCknLFxuICAgICAgd2lkdGg6IDQsXG4gICAgICBoZWlnaHQ6IDQsXG4gICAgICBib3JkZXJSYWRpdXM6ICdmdWxsJyxcbiAgICAgIGJnOiAnaHlwZXInLFxuICAgIH0sXG4gIH0sXG4gIGlzU2VsZWN0ZWQ6IHtcbiAgICBiZzogJ3RleHQnLFxuICAgIGNvbG9yOiAnYmFja2dyb3VuZCcsXG4gICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICBiZzogJ3NlY29uZGFyeS1ob3ZlcicsXG4gICAgICBjb2xvcjogJ2JhY2tncm91bmQnLFxuICAgIH0sXG4gICAgJyY6OmFmdGVyJzoge1xuICAgICAgYmc6ICdiYWNrZ3JvdW5kJyxcbiAgICB9LFxuICB9LFxuICBpc1JhbmdlU3RhcnQ6IHtcbiAgICBib3JkZXJSYWRpdXNSaWdodDogJ25vbmUnLFxuICB9LFxuICBpc1JhbmdlRW5kOiB7XG4gICAgYm9yZGVyUmFkaXVzTGVmdDogJ25vbmUnLFxuICB9LFxuICBpc0luUmFuZ2U6IHtcbiAgICBiZzogJ3RleHQtZGlzYWJsZWQnLFxuICAgIGNvbG9yOiAnYmFja2dyb3VuZCcsXG4gICAgYm9yZGVyUmFkaXVzOiAnbm9uZScsXG4gICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICBiZzogJ3NlY29uZGFyeS1ob3ZlcicsXG4gICAgICBjb2xvcjogJ2JhY2tncm91bmQnLFxuICAgIH0sXG4gICAgJyY6OmFmdGVyJzoge1xuICAgICAgYmc6ICdiYWNrZ3JvdW5kJyxcbiAgICB9LFxuICB9LFxuICBpc0Rpc2FibGVkOiB7XG4gICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICBiZzogJ3RyYW5zcGFyZW50JyxcbiAgICBjdXJzb3I6ICdub3QtYWxsb3dlZCcsXG4gICAgdXNlclNlbGVjdDogJ25vbmUnLFxuICAgIHRleHREZWNvcmF0aW9uOiAnbGluZS10aHJvdWdoJyxcbiAgICAnJjpob3Zlcic6IHtcbiAgICAgIGNvbG9yOiAndGV4dC1kaXNhYmxlZCcsXG4gICAgICBiZzogJ3RyYW5zcGFyZW50JyxcbiAgICAgIHRleHREZWNvcmF0aW9uOiAnbGluZS10aHJvdWdoJyxcbiAgICAgIGN1cnNvcjogJ25vdC1hbGxvd2VkJyxcbiAgICAgIHVzZXJTZWxlY3Q6ICdub25lJyxcbiAgICB9LFxuICB9LFxufSk7XG5cbnR5cGUgRGF0ZUNlbGxQcm9wcyA9IFN0eWxlUHJvcHM8dHlwZW9mIGRhdGVjZWxsU3RhdGVzPjtcblxuZXhwb3J0IGNvbnN0IERhdGVDZWxsID0gc3R5bGVkLnRkPERhdGVDZWxsUHJvcHM+KFxuICBjc3Moe1xuICAgIGZvbnRXZWlnaHQ6ICdiYXNlJyxcbiAgICB3aWR0aDogJzMycHgnLFxuICAgIGhlaWdodDogJzMycHgnLFxuICAgIHRleHRBbGlnbjogJ2NlbnRlcicsXG4gICAgcGFkZGluZzogMCxcbiAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICBib3JkZXJSYWRpdXM6ICdtZCcsXG4gICAgdHJhbnNpdGlvbjogdHJhbnNpdGlvbkNvbmNhdChcbiAgICAgIFsnYm9yZGVyLWNvbG9yJywgJ2NvbG9yJywgJ2JhY2tncm91bmQtY29sb3InLCAnYm94LXNoYWRvdyddLFxuICAgICAgJ2Zhc3QnLFxuICAgICAgJ2Vhc2UtaW4nXG4gICAgKSxcbiAgICAnJjpob3Zlcic6IHtcbiAgICAgIGNvbG9yOiAnc2Vjb25kYXJ5JyxcbiAgICAgIGJnOiAnYmFja2dyb3VuZC1ob3ZlcicsXG4gICAgICB0cmFuc2l0aW9uOiB0cmFuc2l0aW9uQ29uY2F0KFxuICAgICAgICBbJ2JhY2tncm91bmQtY29sb3InLCAnYm94LXNoYWRvdyddLFxuICAgICAgICAnZmFzdCcsXG4gICAgICAgICdlYXNlLWluJ1xuICAgICAgKSxcbiAgICAgIGN1cnNvcjogJ3BvaW50ZXInLFxuICAgIH0sXG4gICAgJyY6Zm9jdXMtdmlzaWJsZSc6IHtcbiAgICAgIGNvbG9yOiAnc2Vjb25kYXJ5JyxcbiAgICAgIG91dGxpbmU6ICdub25lJyxcbiAgICB9LFxuICAgICcmOmFjdGl2ZSc6IHtcbiAgICAgIGNvbG9yOiAndGV4dCcsXG4gICAgfSxcbiAgICAnJjo6YmVmb3JlJzoge1xuICAgICAgY29udGVudDogJ1wiXCInLFxuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICBpbnNldDogLTMsXG4gICAgICBib3JkZXJSYWRpdXM6ICdsZycsXG4gICAgICBib3JkZXI6IDIsXG4gICAgICBvcGFjaXR5OiAwLFxuICAgICAgekluZGV4OiAwLFxuICAgIH0sXG4gICAgJyY6Zm9jdXMtdmlzaWJsZTo6YmVmb3JlJzoge1xuICAgICAgb3BhY2l0eTogMSxcbiAgICB9LFxuICB9KSxcbiAgZGF0ZWNlbGxTdGF0ZXNcbik7XG4iXX0= */");
@@ -0,0 +1,28 @@
1
+ import type { IsoWeekday } from '../../utils/locale';
2
+ /**
3
+ * Capitalize the first character of a string using the locale; rest unchanged (e.g. "next month" → "Next month").
4
+ */
5
+ export declare const capitalizeFirst: (str: string, locale: Intl.Locale) => string;
6
+ /**
7
+ * Format month and year for the calendar header (e.g. "February 2026").
8
+ */
9
+ export declare const formatMonthYear: (date: Date, locale: Intl.Locale) => string;
10
+ /**
11
+ * Get weekday names for column headers or abbr attributes.
12
+ * Column order follows `firstWeekday` (ISO 1 = Monday … 7 = Sunday), matching `Intl.Locale#getWeekInfo().firstDay`.
13
+ * @param format - 'short' for abbreviated (e.g. "Su", "Mo"), 'long' for full (e.g. "Sunday", "Monday")
14
+ */
15
+ export declare const getWeekdayNames: (format: "short" | "long", locale: Intl.Locale, firstWeekday: IsoWeekday) => string[];
16
+ /**
17
+ * Get localized "next month" and "previous month" labels for calendar nav.
18
+ * Uses Intl.RelativeTimeFormat with numeric: "auto" (e.g. "next month", "last month").
19
+ */
20
+ export declare const getRelativeMonthLabels: (locale: Intl.Locale) => {
21
+ nextMonth: string;
22
+ lastMonth: string;
23
+ };
24
+ /**
25
+ * Get localized "today" label (e.g. "today").
26
+ */
27
+ export declare const getRelativeTodayLabel: (locale: Intl.Locale) => string;
28
+ export declare const formatDateForAriaLabel: (date: Date, locale: Intl.Locale) => string;
@@ -0,0 +1,72 @@
1
+ import { stringifyLocale } from '../../utils/locale';
2
+
3
+ /**
4
+ * Capitalize the first character of a string using the locale; rest unchanged (e.g. "next month" → "Next month").
5
+ */
6
+ export const capitalizeFirst = (str, locale) => str.length === 0 ? str : str[0].toLocaleUpperCase(stringifyLocale(locale)) + str.slice(1);
7
+
8
+ /**
9
+ * Format month and year for the calendar header (e.g. "February 2026").
10
+ */
11
+ export const formatMonthYear = (date, locale) => {
12
+ return new Intl.DateTimeFormat(stringifyLocale(locale), {
13
+ month: 'long',
14
+ year: 'numeric'
15
+ }).format(date);
16
+ };
17
+
18
+ /**
19
+ * Get weekday names for column headers or abbr attributes.
20
+ * Column order follows `firstWeekday` (ISO 1 = Monday … 7 = Sunday), matching `Intl.Locale#getWeekInfo().firstDay`.
21
+ * @param format - 'short' for abbreviated (e.g. "Su", "Mo"), 'long' for full (e.g. "Sunday", "Monday")
22
+ */
23
+ export const getWeekdayNames = (format, locale, firstWeekday) => {
24
+ const formatter = new Intl.DateTimeFormat(stringifyLocale(locale), {
25
+ weekday: format
26
+ });
27
+ const monday = new Date(2024, 0, 8);
28
+ const namesMonToSun = Array.from({
29
+ length: 7
30
+ }, (_, i) => {
31
+ const date = new Date(monday);
32
+ date.setDate(monday.getDate() + i);
33
+ return formatter.format(date);
34
+ });
35
+ return Array.from({
36
+ length: 7
37
+ }, (_, j) => {
38
+ const iso = (firstWeekday - 1 + j) % 7 + 1;
39
+ return namesMonToSun[iso - 1];
40
+ });
41
+ };
42
+
43
+ /**
44
+ * Get localized "next month" and "previous month" labels for calendar nav.
45
+ * Uses Intl.RelativeTimeFormat with numeric: "auto" (e.g. "next month", "last month").
46
+ */
47
+ export const getRelativeMonthLabels = locale => {
48
+ const rtf = new Intl.RelativeTimeFormat(stringifyLocale(locale), {
49
+ numeric: 'auto'
50
+ });
51
+ return {
52
+ nextMonth: capitalizeFirst(rtf.format(1, 'month'), locale),
53
+ lastMonth: capitalizeFirst(rtf.format(-1, 'month'), locale)
54
+ };
55
+ };
56
+
57
+ /**
58
+ * Get localized "today" label (e.g. "today").
59
+ */
60
+ export const getRelativeTodayLabel = locale => {
61
+ const rtf = new Intl.RelativeTimeFormat(stringifyLocale(locale), {
62
+ numeric: 'auto'
63
+ });
64
+ return capitalizeFirst(rtf.format(0, 'day'), locale);
65
+ };
66
+ export const formatDateForAriaLabel = (date, locale) => {
67
+ return new Intl.DateTimeFormat(stringifyLocale(locale), {
68
+ month: 'long',
69
+ day: 'numeric',
70
+ year: 'numeric'
71
+ }).format(date);
72
+ };
@@ -0,0 +1,12 @@
1
+ import type { CalendarBodyProps } from '../types';
2
+ import { type DateWithRow } from './dateGrid';
3
+ /** Calendar grid props and callbacks used by `keyHandler`, aligned with `CalendarBodyProps`. */
4
+ export type KeyHandlerParams = Pick<CalendarBodyProps, 'onFocusedDateChange' | 'onDateSelect' | 'onDisplayDateChange' | 'onEscapeKeyPress' | 'hasAdjacentMonthRight' | 'hasAdjacentMonthLeft' | 'disabledDates'> & {
5
+ e: React.KeyboardEvent;
6
+ /** The date for the day cell that received the key event */
7
+ date: Date;
8
+ datesWithRow: DateWithRow[];
9
+ month: number;
10
+ year: number;
11
+ };
12
+ export declare const keyHandler: ({ e, date, onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onDisplayDateChange, hasAdjacentMonthRight, hasAdjacentMonthLeft, }: KeyHandlerParams) => void;
@@ -0,0 +1,126 @@
1
+ import { isDateDisabled } from './dateGrid';
2
+
3
+ /** Calendar grid props and callbacks used by `keyHandler`, aligned with `CalendarBodyProps`. */
4
+
5
+ /**
6
+ * Clamp a day to the last day of the given month (e.g. Jan 31 -> Feb 28).
7
+ */
8
+ const clampToMonth = (year, month, day) => {
9
+ const last = new Date(year, month + 1, 0).getDate();
10
+ return new Date(year, month, Math.min(day, last));
11
+ };
12
+ export const keyHandler = ({
13
+ e,
14
+ date,
15
+ onFocusedDateChange,
16
+ datesWithRow,
17
+ month,
18
+ year,
19
+ disabledDates = [],
20
+ onDateSelect,
21
+ onEscapeKeyPress,
22
+ onDisplayDateChange,
23
+ hasAdjacentMonthRight,
24
+ hasAdjacentMonthLeft
25
+ }) => {
26
+ const idx = datesWithRow.findIndex(({
27
+ date: dateWithRow
28
+ }) => dateWithRow.getTime() === date.getTime());
29
+ if (idx < 0) return;
30
+ const currentRow = datesWithRow[idx].rowIndex;
31
+ const day = date.getDate();
32
+ const hasRight = !!hasAdjacentMonthRight;
33
+ const hasLeft = !!hasAdjacentMonthLeft;
34
+ let newDate = null;
35
+ let newDisplayDate = null;
36
+ switch (e.key) {
37
+ case 'ArrowLeft':
38
+ e.preventDefault();
39
+ if (idx > 0) {
40
+ newDate = datesWithRow[idx - 1].date;
41
+ } else {
42
+ const lastDayPrevMonth = new Date(year, month, 0);
43
+ newDate = lastDayPrevMonth;
44
+ if (!hasLeft) {
45
+ newDisplayDate = new Date(year, month - 1, 1);
46
+ }
47
+ }
48
+ break;
49
+ case 'ArrowRight':
50
+ e.preventDefault();
51
+ if (idx < datesWithRow.length - 1) {
52
+ newDate = datesWithRow[idx + 1].date;
53
+ } else {
54
+ newDate = new Date(year, month + 1, 1);
55
+ if (!hasRight) {
56
+ newDisplayDate = new Date(year, month + 1, 1);
57
+ }
58
+ }
59
+ break;
60
+ case 'ArrowUp':
61
+ e.preventDefault();
62
+ newDate = new Date(date);
63
+ newDate.setDate(newDate.getDate() - 7);
64
+ if (newDate.getMonth() !== month || newDate.getFullYear() !== year) {
65
+ if (!hasLeft) {
66
+ newDisplayDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
67
+ }
68
+ }
69
+ break;
70
+ case 'ArrowDown':
71
+ e.preventDefault();
72
+ newDate = new Date(date);
73
+ newDate.setDate(newDate.getDate() + 7);
74
+ if (newDate.getMonth() !== month || newDate.getFullYear() !== year) {
75
+ if (!hasRight) {
76
+ newDisplayDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
77
+ }
78
+ }
79
+ break;
80
+ case 'Home':
81
+ e.preventDefault();
82
+ newDate = datesWithRow.find(({
83
+ rowIndex
84
+ }) => rowIndex === currentRow)?.date ?? date;
85
+ break;
86
+ case 'End':
87
+ e.preventDefault();
88
+ newDate = [...datesWithRow].reverse().find(({
89
+ rowIndex
90
+ }) => rowIndex === currentRow)?.date ?? date;
91
+ break;
92
+ case 'PageDown':
93
+ e.preventDefault();
94
+ if (e.shiftKey) {
95
+ newDate = clampToMonth(year + 1, month, day);
96
+ } else {
97
+ newDate = clampToMonth(year, month + 1, day);
98
+ }
99
+ newDisplayDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
100
+ break;
101
+ case 'PageUp':
102
+ e.preventDefault();
103
+ if (e.shiftKey) {
104
+ newDate = clampToMonth(year - 1, month, day);
105
+ } else {
106
+ newDate = clampToMonth(year, month - 1, day);
107
+ }
108
+ newDisplayDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1);
109
+ break;
110
+ case 'Enter':
111
+ case ' ':
112
+ e.preventDefault();
113
+ if (!isDateDisabled(date, disabledDates)) onDateSelect(date);
114
+ return;
115
+ case 'Escape':
116
+ e.preventDefault();
117
+ onEscapeKeyPress?.();
118
+ return;
119
+ default:
120
+ return;
121
+ }
122
+ if (newDate !== null) {
123
+ onFocusedDateChange(newDate);
124
+ if (newDisplayDate !== null) onDisplayDateChange?.(newDisplayDate);
125
+ }
126
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Validation helpers for DatePicker (single-date).
3
+ * Used to mark invalid dates as unselectable and for manual entry validation.
4
+ */
5
+ /**
6
+ * Check if a date is in the past (before today at start of day).
7
+ * Useful for disabling past dates in the calendar.
8
+ */
9
+ export declare const isPastDate: (date: Date) => boolean;
10
+ /**
11
+ * Check if a date is valid (finite and not NaN).
12
+ */
13
+ export declare const isValidDate: (date: Date) => boolean;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Validation helpers for DatePicker (single-date).
3
+ * Used to mark invalid dates as unselectable and for manual entry validation.
4
+ */
5
+
6
+ /**
7
+ * Check if a date is in the past (before today at start of day).
8
+ * Useful for disabling past dates in the calendar.
9
+ */
10
+ export const isPastDate = date => {
11
+ const today = new Date();
12
+ today.setHours(0, 0, 0, 0);
13
+ const normalizedDate = new Date(date);
14
+ normalizedDate.setHours(0, 0, 0, 0);
15
+ return normalizedDate.getTime() < today.getTime();
16
+ };
17
+
18
+ /**
19
+ * Check if a date is valid (finite and not NaN).
20
+ */
21
+ export const isValidDate = date => {
22
+ return date instanceof Date && !Number.isNaN(date.getTime());
23
+ };
@@ -0,0 +1,7 @@
1
+ import type { DatePickerProps } from './types';
2
+ /**
3
+ * DatePicker: single-date or range. Holds shared state and provides it via context.
4
+ * Single: selectedDate, setSelectedDate. Range: startDate, endDate, setStartDate, setEndDate.
5
+ * With no children, renders default layout (input + calendar popover).
6
+ */
7
+ export declare const DatePicker: React.FC<DatePickerProps>;
@@ -0,0 +1,157 @@
1
+ import { MiniArrowRightIcon } from '@codecademy/gamut-icons';
2
+ import { useCallback, useId, useMemo, useRef, useState } from 'react';
3
+ import { Box, FlexBox } from '../Box';
4
+ import { PopoverContainer } from '../PopoverContainer';
5
+ import { DatePickerCalendar } from './DatePickerCalendar';
6
+ import { DatePickerProvider } from './DatePickerContext';
7
+ import { DatePickerInput } from './DatePickerInput';
8
+ import { isRangeProps } from './utils/dateSelect';
9
+ import { useResolvedLocale } from './utils/locale';
10
+ import { DEFAULT_DATE_PICKER_TRANSLATIONS } from './utils/translations';
11
+
12
+ /**
13
+ * DatePicker: single-date or range. Holds shared state and provides it via context.
14
+ * Single: selectedDate, setSelectedDate. Range: startDate, endDate, setStartDate, setEndDate.
15
+ * With no children, renders default layout (input + calendar popover).
16
+ */
17
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
18
+ export const DatePicker = props => {
19
+ const {
20
+ locale,
21
+ disabledDates = [],
22
+ placeholder,
23
+ mode,
24
+ children,
25
+ translations: translationsProp,
26
+ inputSize
27
+ } = props;
28
+ const [isCalendarOpen, setIsCalendarOpen] = useState(false);
29
+ const [focusGridSignal, setFocusGridSignal] = useState(false);
30
+ const [gridFocusRequested, setGridFocusRequested] = useState(false);
31
+ const [activeRangePart, setActiveRangePart] = useState(null);
32
+ const inputRef = useRef(null);
33
+ const dialogId = useId();
34
+ const calendarDialogId = `datepicker-dialog-${dialogId.replace(/:/g, '')}`;
35
+ const clearGridFocusRequest = useCallback(() => {
36
+ setGridFocusRequested(false);
37
+ }, []);
38
+ const resolvedLocale = useResolvedLocale(locale);
39
+ const openCalendar = useCallback(options => {
40
+ const moveFocus = options?.moveFocusIntoCalendar ?? false;
41
+ setIsCalendarOpen(true);
42
+ if (moveFocus) {
43
+ setGridFocusRequested(true);
44
+ setFocusGridSignal(signal => !signal);
45
+ } else {
46
+ setGridFocusRequested(false);
47
+ }
48
+ }, []);
49
+ const focusCalendarGrid = useCallback(() => {
50
+ setGridFocusRequested(true);
51
+ setFocusGridSignal(signal => !signal);
52
+ }, []);
53
+ const closeCalendar = useCallback(() => {
54
+ setIsCalendarOpen(false);
55
+ setActiveRangePart(null);
56
+ setGridFocusRequested(false);
57
+ const shell = inputRef.current;
58
+ const toFocus = shell?.querySelector('[role="spinbutton"]') ?? shell;
59
+ toFocus?.focus();
60
+ }, []);
61
+ const startOrSelectedDate = isRangeProps(props) ? props.startDate : props.selectedDate;
62
+ const endDate = isRangeProps(props) ? props.endDate : null;
63
+ const setSelection = useCallback((start, end) => {
64
+ if (isRangeProps(props)) {
65
+ props.setStartDate(start);
66
+ props.setEndDate(end ?? null);
67
+ } else {
68
+ props.setSelectedDate(start);
69
+ }
70
+ }, [props]);
71
+ const contextValue = useMemo(() => {
72
+ const translations = {
73
+ ...DEFAULT_DATE_PICKER_TRANSLATIONS,
74
+ ...translationsProp
75
+ };
76
+ const base = {
77
+ startOrSelectedDate,
78
+ setSelection,
79
+ isCalendarOpen,
80
+ openCalendar,
81
+ focusCalendarGrid,
82
+ focusGridSignal,
83
+ gridFocusRequested,
84
+ clearGridFocusRequest,
85
+ closeCalendar,
86
+ locale: resolvedLocale,
87
+ disabledDates,
88
+ calendarDialogId,
89
+ translations
90
+ };
91
+ return mode === 'range' ? {
92
+ ...base,
93
+ mode: 'range',
94
+ endDate,
95
+ activeRangePart,
96
+ setActiveRangePart
97
+ } : {
98
+ ...base,
99
+ mode: 'single'
100
+ };
101
+ }, [mode, startOrSelectedDate, endDate, setSelection, activeRangePart, setActiveRangePart, isCalendarOpen, openCalendar, focusCalendarGrid, focusGridSignal, gridFocusRequested, clearGridFocusRequest, closeCalendar, resolvedLocale, disabledDates, calendarDialogId, translationsProp]);
102
+ const content = children !== undefined ? children : /*#__PURE__*/_jsxs(_Fragment, {
103
+ children: [/*#__PURE__*/_jsx(FlexBox, {
104
+ gap: inputSize === 'small' ? 4 : 8,
105
+ ref: inputRef,
106
+ width: "fit-content",
107
+ children: mode === 'range' ? /*#__PURE__*/_jsxs(_Fragment, {
108
+ children: [/*#__PURE__*/_jsx(DatePickerInput, {
109
+ label: props.startLabel,
110
+ placeholder: placeholder,
111
+ rangePart: "start",
112
+ size: inputSize
113
+ }), /*#__PURE__*/_jsx(Box, {
114
+ alignSelf: "center",
115
+ mt: 32,
116
+ children: /*#__PURE__*/_jsx(MiniArrowRightIcon, {})
117
+ }), /*#__PURE__*/_jsx(DatePickerInput, {
118
+ label: props.endLabel,
119
+ placeholder: placeholder,
120
+ rangePart: "end",
121
+ size: inputSize
122
+ })]
123
+ }) : /*#__PURE__*/_jsx(DatePickerInput, {
124
+ label: props.label,
125
+ placeholder: placeholder
126
+ // ref={inputRef}
127
+ ,
128
+ size: inputSize
129
+ })
130
+ }), /*#__PURE__*/_jsx(PopoverContainer, {
131
+ alignment: "bottom-left",
132
+ allowPageInteraction: true,
133
+ focusOnProps: {
134
+ autoFocus: false,
135
+ focusLock: false
136
+ },
137
+ invertAxis: "x",
138
+ isOpen: isCalendarOpen,
139
+ targetRef: inputRef,
140
+ x: -20,
141
+ y: -16,
142
+ onRequestClose: closeCalendar,
143
+ children: /*#__PURE__*/_jsx("div", {
144
+ "aria-label": contextValue.translations.calendarDialogAriaLabel,
145
+ id: calendarDialogId,
146
+ role: "dialog",
147
+ children: /*#__PURE__*/_jsx(DatePickerCalendar, {
148
+ dialogId: calendarDialogId
149
+ })
150
+ })
151
+ })]
152
+ });
153
+ return /*#__PURE__*/_jsx(DatePickerProvider, {
154
+ value: contextValue,
155
+ children: content
156
+ });
157
+ };
@@ -0,0 +1,11 @@
1
+ import type { CalendarBodyProps } from './Calendar/types';
2
+ export type DatePickerCalendarProps = Pick<CalendarBodyProps, 'weekStartsOn'> & {
3
+ /** id for the dialog (for aria-controls from input). */
4
+ dialogId: string;
5
+ };
6
+ /**
7
+ * Calendar that composes Calendar, CalendarHeader, CalendarBody, CalendarFooter.
8
+ * When inside DatePicker: owns local visibleDate and focusedDate; updates shared
9
+ * state via context. Supports single-date and range modes.
10
+ */
11
+ export declare const DatePickerCalendar: React.FC<DatePickerCalendarProps>;