use-calendar.mjs 4.4 KB

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