use-calendar.mjs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { ref, computed } from 'vue';
  2. import dayjs from 'dayjs';
  3. import { useLocale } from '../../../hooks/use-locale/index.mjs';
  4. import { INPUT_EVENT, UPDATE_MODEL_EVENT } from '../../../constants/event.mjs';
  5. import { isArray, isDate } from '@vue/shared';
  6. import { debugWarn } from '../../../utils/error.mjs';
  7. const adjacentMonth = (start, end) => {
  8. const firstMonthLastDay = start.endOf("month");
  9. const lastMonthFirstDay = end.startOf("month");
  10. const isSameWeek = firstMonthLastDay.isSame(lastMonthFirstDay, "week");
  11. const lastMonthStartDay = isSameWeek ? lastMonthFirstDay.add(1, "week") : lastMonthFirstDay;
  12. return [
  13. [start, firstMonthLastDay],
  14. [lastMonthStartDay.startOf("week"), end]
  15. ];
  16. };
  17. const threeConsecutiveMonth = (start, end) => {
  18. const firstMonthLastDay = start.endOf("month");
  19. const secondMonthFirstDay = start.add(1, "month").startOf("month");
  20. const secondMonthStartDay = firstMonthLastDay.isSame(secondMonthFirstDay, "week") ? secondMonthFirstDay.add(1, "week") : secondMonthFirstDay;
  21. const secondMonthLastDay = secondMonthStartDay.endOf("month");
  22. const lastMonthFirstDay = end.startOf("month");
  23. const lastMonthStartDay = secondMonthLastDay.isSame(lastMonthFirstDay, "week") ? lastMonthFirstDay.add(1, "week") : lastMonthFirstDay;
  24. return [
  25. [start, firstMonthLastDay],
  26. [secondMonthStartDay.startOf("week"), secondMonthLastDay],
  27. [lastMonthStartDay.startOf("week"), end]
  28. ];
  29. };
  30. const useCalendar = (props, emit, componentName) => {
  31. const { lang } = useLocale();
  32. const selectedDay = ref();
  33. const now = dayjs().locale(lang.value);
  34. const realSelectedDay = computed({
  35. get() {
  36. if (!props.modelValue)
  37. return selectedDay.value;
  38. return date.value;
  39. },
  40. set(val) {
  41. if (!val)
  42. return;
  43. selectedDay.value = val;
  44. const result = val.toDate();
  45. emit(INPUT_EVENT, result);
  46. emit(UPDATE_MODEL_EVENT, result);
  47. }
  48. });
  49. const validatedRange = computed(() => {
  50. if (!props.range || !isArray(props.range) || props.range.length !== 2 || props.range.some((item) => !isDate(item)))
  51. return [];
  52. const rangeArrDayjs = props.range.map((_) => dayjs(_).locale(lang.value));
  53. const [startDayjs, endDayjs] = rangeArrDayjs;
  54. if (startDayjs.isAfter(endDayjs)) {
  55. debugWarn(componentName, "end time should be greater than start time");
  56. return [];
  57. }
  58. if (startDayjs.isSame(endDayjs, "month")) {
  59. return calculateValidatedDateRange(startDayjs, endDayjs);
  60. } else {
  61. if (startDayjs.add(1, "month").month() !== endDayjs.month()) {
  62. debugWarn(componentName, "start time and end time interval must not exceed two months");
  63. return [];
  64. }
  65. return calculateValidatedDateRange(startDayjs, endDayjs);
  66. }
  67. });
  68. const date = computed(() => {
  69. if (!props.modelValue) {
  70. return realSelectedDay.value || (validatedRange.value.length ? validatedRange.value[0][0] : now);
  71. } else {
  72. return dayjs(props.modelValue).locale(lang.value);
  73. }
  74. });
  75. const prevMonthDayjs = computed(() => date.value.subtract(1, "month").date(1));
  76. const nextMonthDayjs = computed(() => date.value.add(1, "month").date(1));
  77. const prevYearDayjs = computed(() => date.value.subtract(1, "year").date(1));
  78. const nextYearDayjs = computed(() => date.value.add(1, "year").date(1));
  79. const calculateValidatedDateRange = (startDayjs, endDayjs) => {
  80. const firstDay = startDayjs.startOf("week");
  81. const lastDay = endDayjs.endOf("week");
  82. const firstMonth = firstDay.get("month");
  83. const lastMonth = lastDay.get("month");
  84. if (firstMonth === lastMonth) {
  85. return [[firstDay, lastDay]];
  86. } else if ((firstMonth + 1) % 12 === lastMonth) {
  87. return adjacentMonth(firstDay, lastDay);
  88. } else if (firstMonth + 2 === lastMonth || (firstMonth + 1) % 11 === lastMonth) {
  89. return threeConsecutiveMonth(firstDay, lastDay);
  90. } else {
  91. debugWarn(componentName, "start time and end time interval must not exceed two months");
  92. return [];
  93. }
  94. };
  95. const pickDay = (day) => {
  96. realSelectedDay.value = day;
  97. };
  98. const selectDate = (type) => {
  99. const dateMap = {
  100. "prev-month": prevMonthDayjs.value,
  101. "next-month": nextMonthDayjs.value,
  102. "prev-year": prevYearDayjs.value,
  103. "next-year": nextYearDayjs.value,
  104. today: now
  105. };
  106. const day = dateMap[type];
  107. if (!day.isSame(date.value, "day")) {
  108. pickDay(day);
  109. }
  110. };
  111. return {
  112. calculateValidatedDateRange,
  113. date,
  114. realSelectedDay,
  115. pickDay,
  116. selectDate,
  117. validatedRange
  118. };
  119. };
  120. export { useCalendar };
  121. //# sourceMappingURL=use-calendar.mjs.map