yearAndMonthFoundation.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { setMonth, setYear } from 'date-fns';
  2. import BaseFoundation, { DefaultAdapter } from '../base/foundation';
  3. import { PresetPosition } from './foundation';
  4. export interface YearAndMonthFoundationProps {
  5. currentYear?: number;
  6. currentMonth?: number;
  7. onSelect?: (obj: { currentMonth: number; currentYear: number }) => void;
  8. onBackToMain?: () => void;
  9. locale?: any;
  10. localeCode?: string;
  11. monthCycled?: boolean;
  12. yearCycled?: boolean;
  13. noBackBtn?: boolean;
  14. disabledDate?: (date: Date) => boolean;
  15. density?: string;
  16. presetPosition?: PresetPosition;
  17. renderQuickControls?: any;
  18. renderDateInput?: any;
  19. yearAndMonthOpts?: any
  20. }
  21. export interface YearAndMonthFoundationState {
  22. years: Array<{ value: number; year: number }>;
  23. months: Array<{ value: number; month: number }>;
  24. currentYear: number;
  25. currentMonth: number
  26. }
  27. export interface YearAndMonthAdapter extends DefaultAdapter<YearAndMonthFoundationProps, YearAndMonthFoundationState> {
  28. setCurrentYear: (currentYear: number, cb?: () => void) => void;
  29. setCurrentMonth: (currentMonth: number) => void;
  30. notifySelectYear: (year: number) => void;
  31. notifySelectMonth: (month: number) => void;
  32. notifyBackToMain: () => void
  33. }
  34. export interface MonthScrollItem {
  35. [k: string]: any;
  36. month: number;
  37. value: string;
  38. disabled: boolean
  39. }
  40. export interface YearScrollItem {
  41. [k: string]: any;
  42. year: number;
  43. value: number;
  44. disabled: boolean
  45. }
  46. export default class YearAndMonthFoundation extends BaseFoundation<YearAndMonthAdapter> {
  47. constructor(adapter: YearAndMonthAdapter) {
  48. super({ ...adapter });
  49. }
  50. // eslint-disable-next-line @typescript-eslint/no-empty-function
  51. init() {}
  52. // eslint-disable-next-line @typescript-eslint/no-empty-function
  53. destroy() {}
  54. selectYear(item: YearScrollItem) {
  55. const year = item.value;
  56. this._adapter.setCurrentYear(year, () => this.autoSelectMonth(item));
  57. this._adapter.notifySelectYear(year);
  58. }
  59. selectMonth(item: MonthScrollItem) {
  60. const { month } = item;
  61. this._adapter.setCurrentMonth(month);
  62. this._adapter.notifySelectMonth(month);
  63. }
  64. /**
  65. * After selecting a year, if the currentMonth is disabled, automatically select a non-disabled month
  66. */
  67. autoSelectMonth(item: YearScrollItem) {
  68. const { disabledDate, locale } = this._adapter.getProps();
  69. const { months, currentMonth } = this._adapter.getStates();
  70. const currentDate = setYear(Date.now(), item.year);
  71. const isCurrentMonthDisabled = disabledDate(setMonth(currentDate, currentMonth - 1));
  72. if (isCurrentMonthDisabled) {
  73. const currentIndex = months.findIndex(({ month }) => month === currentMonth);
  74. let validMonth: typeof months[number];
  75. // First look in the back, if you can't find it in the back, then look in the front
  76. validMonth = months.slice(currentIndex).find(({ month }) => !disabledDate(setMonth(currentDate, month - 1)));
  77. if (!validMonth) {
  78. validMonth = months.slice(0, currentIndex).find(({ month }) => !disabledDate(setMonth(currentDate, month - 1)));
  79. }
  80. if (validMonth) {
  81. this.selectMonth({ month: validMonth.month, value: locale.fullMonths[validMonth.month], disabled: false });
  82. }
  83. }
  84. }
  85. backToMain() {
  86. this._adapter.notifyBackToMain();
  87. }
  88. }