{"version":3,"file":"basic-date-table.mjs","sources":["../../../../../../../packages/components/date-picker/src/date-picker-com/basic-date-table.vue"],"sourcesContent":["<template>\r\n  <table\r\n    cellspacing=\"0\"\r\n    cellpadding=\"0\"\r\n    class=\"sg-date-table\"\r\n    :class=\"{ 'is-week-mode': selectionMode === 'week' }\"\r\n    @click=\"handleClick\"\r\n    @mousemove=\"handleMouseMove\"\r\n  >\r\n    <tbody>\r\n      <tr>\r\n        <th v-if=\"showWeekNumber\">{{ t('sg.datepicker.week') }}</th>\r\n        <th v-for=\"(week, key) in WEEKS\" :key=\"key\">\r\n          {{ t('sg.datepicker.weeks.' + week) }}\r\n        </th>\r\n      </tr>\r\n      <tr\r\n        v-for=\"(row, key) in rows\"\r\n        :key=\"key\"\r\n        class=\"sg-date-table__row\"\r\n        :class=\"{ current: isWeekActive(row[1]) }\"\r\n      >\r\n        <td\r\n          v-for=\"(cell, key_) in row\"\r\n          :key=\"key_\"\r\n          :class=\"getCellClasses(cell)\"\r\n        >\r\n          <sg-date-picker-cell :cell=\"cell\" />\r\n        </td>\r\n      </tr>\r\n    </tbody>\r\n  </table>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport { defineComponent, computed, ref } from 'vue'\r\nimport dayjs from 'dayjs'\r\nimport { useLocale } from '@sgui-plus/hooks'\r\nimport { coerceTruthyValueToArray } from '@sgui-plus/utils/util'\r\nimport SgDatePickerCell from './basic-cell-render'\r\nimport type { PropType } from 'vue'\r\n\r\nimport type { Dayjs } from 'dayjs'\r\nimport type { DateCell } from '../date-picker.type'\r\n\r\nexport default defineComponent({\r\n  components: {\r\n    SgDatePickerCell,\r\n  },\r\n  props: {\r\n    date: {\r\n      type: Object as PropType<Dayjs>,\r\n    },\r\n    minDate: {\r\n      type: Object as PropType<Dayjs>,\r\n    },\r\n    maxDate: {\r\n      type: Object as PropType<Dayjs>,\r\n    },\r\n    parsedValue: {\r\n      type: [Object, Array] as PropType<Dayjs | Dayjs[]>,\r\n    },\r\n    selectionMode: {\r\n      type: String,\r\n      default: 'day',\r\n    },\r\n    showWeekNumber: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    disabledDate: {\r\n      type: Function,\r\n    },\r\n    cellClassName: {\r\n      type: Function,\r\n    },\r\n    shortcuts: {\r\n      type: Array,\r\n      default: []\r\n    },\r\n    rangeState: {\r\n      type: Object,\r\n      default: () => ({\r\n        endDate: null,\r\n        selecting: false,\r\n      }),\r\n    },\r\n  },\r\n  emits: ['changerange', 'pick', 'select', 'confirmToday'],\r\n\r\n  setup(props, ctx) {\r\n    const { t, lang } = useLocale()\r\n    // data\r\n    const lastRow = ref<number | null>(null)\r\n    const lastColumn = ref<number | null>(null)\r\n    const tableRows = ref<DateCell[][]>([[], [], [], [], [], []])\r\n\r\n    // todo better way to get Day.js locale object\r\n    const firstDayOfWeek = (props.date as any).$locale().weekStart || 7\r\n    const WEEKS_CONSTANT = props.date!\r\n      .locale('en')\r\n      .localeData()\r\n      .weekdaysShort()\r\n      .map((_) => _.toLowerCase())\r\n\r\n    const offsetDay = computed(() => {\r\n      // Sunday 7(0), cal the left and right offset days, 3217654, such as Monday is -1, the is to adjust the position of the first two rows of dates\r\n      return firstDayOfWeek > 3 ? 7 - firstDayOfWeek : -firstDayOfWeek\r\n    })\r\n\r\n    const startDate = computed(() => {\r\n      const startDayOfMonth = props.date!.startOf('month')\r\n      return startDayOfMonth.subtract(startDayOfMonth.day() || 7, 'day')\r\n    })\r\n\r\n    const WEEKS = computed(() => {\r\n      return WEEKS_CONSTANT.concat(WEEKS_CONSTANT).slice(\r\n        firstDayOfWeek,\r\n        firstDayOfWeek + 7\r\n      )\r\n    })\r\n\r\n    const rows = computed(() => {\r\n      // TODO: refactory rows / getCellClasses\r\n      const startOfMonth = props.date!.startOf('month')\r\n      const startOfMonthDay = startOfMonth.day() || 7 // day of first day\r\n      const dateCountOfMonth = startOfMonth.daysInMonth()\r\n      const dateCountOfLastMonth = startOfMonth\r\n        .subtract(1, 'month')\r\n        .daysInMonth()\r\n\r\n      const offset = offsetDay.value\r\n      const rows_ = tableRows.value\r\n      let count = 1\r\n\r\n      const selectedDate: Dayjs[] =\r\n        props.selectionMode === 'dates'\r\n          ? coerceTruthyValueToArray(props.parsedValue)\r\n          : []\r\n\r\n      const calNow = dayjs().locale(lang.value).startOf('day')\r\n\r\n      for (let i = 0; i < 6; i++) {\r\n        const row = rows_[i]\r\n\r\n        if (props.showWeekNumber) {\r\n          if (!row[0]) {\r\n            row[0] = {\r\n              type: 'week',\r\n              text: startDate.value.add(i * 7 + 1, 'day').week(),\r\n            }\r\n          }\r\n        }\r\n\r\n        for (let j = 0; j < 7; j++) {\r\n          let cell = row[props.showWeekNumber ? j + 1 : j]\r\n          if (!cell) {\r\n            cell = {\r\n              row: i,\r\n              column: j,\r\n              type: 'normal',\r\n              inRange: false,\r\n              start: false,\r\n              end: false,\r\n            }\r\n          }\r\n          const index = i * 7 + j\r\n          const calTime = startDate.value.add(index - offset, 'day')\r\n          cell.dayjs = calTime\r\n          cell.date = calTime.toDate()\r\n          cell.timestamp = calTime.valueOf()\r\n          cell.type = 'normal'\r\n\r\n          const calEndDate =\r\n            props.rangeState.endDate ||\r\n            props.maxDate ||\r\n            (props.rangeState.selecting && props.minDate)\r\n\r\n          cell.inRange =\r\n            (props.minDate &&\r\n              calTime.isSameOrAfter(props.minDate, 'day') &&\r\n              calEndDate &&\r\n              calTime.isSameOrBefore(calEndDate, 'day')) ||\r\n            (props.minDate &&\r\n              calTime.isSameOrBefore(props.minDate, 'day') &&\r\n              calEndDate &&\r\n              calTime.isSameOrAfter(calEndDate, 'day'))\r\n\r\n          if (props.minDate?.isSameOrAfter(calEndDate)) {\r\n            cell.start = calEndDate && calTime.isSame(calEndDate, 'day')\r\n            cell.end = props.minDate && calTime.isSame(props.minDate, 'day')\r\n          } else {\r\n            cell.start = props.minDate && calTime.isSame(props.minDate, 'day')\r\n            cell.end = calEndDate && calTime.isSame(calEndDate, 'day')\r\n          }\r\n\r\n          const isToday = calTime.isSame(calNow, 'day')\r\n\r\n          if (isToday) {\r\n            cell.type = 'today'\r\n          }\r\n\r\n          if (i >= 0 && i <= 1) {\r\n            const numberOfDaysFromPreviousMonth =\r\n              startOfMonthDay + offset < 0\r\n                ? 7 + startOfMonthDay + offset\r\n                : startOfMonthDay + offset\r\n\r\n            if (j + i * 7 >= numberOfDaysFromPreviousMonth) {\r\n              cell.text = count++\r\n            } else {\r\n              cell.text =\r\n                dateCountOfLastMonth -\r\n                (numberOfDaysFromPreviousMonth - (j % 7)) +\r\n                1 +\r\n                i * 7\r\n              cell.type = 'prev-month'\r\n            }\r\n          } else {\r\n            if (count <= dateCountOfMonth) {\r\n              cell.text = count++\r\n            } else {\r\n              cell.text = count++ - dateCountOfMonth\r\n              cell.type = 'next-month'\r\n            }\r\n          }\r\n\r\n          const cellDate = calTime.toDate()\r\n          cell.selected = selectedDate.find(\r\n            (_) => _.valueOf() === calTime.valueOf()\r\n          )\r\n          cell.isSelected = !!cell.selected\r\n          cell.isCurrent = isCurrent(cell)\r\n          cell.disabled = props.disabledDate && props.disabledDate(cellDate)\r\n          cell.customClass =\r\n            props.cellClassName && props.cellClassName(cellDate)\r\n          row[props.showWeekNumber ? j + 1 : j] = cell\r\n        }\r\n\r\n        if (props.selectionMode === 'week') {\r\n          const start = props.showWeekNumber ? 1 : 0\r\n          const end = props.showWeekNumber ? 7 : 6\r\n          const isActive = isWeekActive(row[start + 1])\r\n          row[start].inRange = isActive\r\n          row[start].start = isActive\r\n          row[end].inRange = isActive\r\n          row[end].end = isActive\r\n        }\r\n      }\r\n      return rows_\r\n    })\r\n\r\n    const isCurrent = (cell): boolean => {\r\n      return (\r\n        props.selectionMode === 'day' &&\r\n        (cell.type === 'normal' || cell.type === 'today') &&\r\n        cellMatchesDate(cell, props.parsedValue)\r\n      )\r\n    }\r\n\r\n    const cellMatchesDate = (cell, date) => {\r\n      if (!date) return false\r\n      return dayjs(date)\r\n        .locale(lang.value)\r\n        .isSame(props.date!.date(Number(cell.text)), 'day')\r\n    }\r\n\r\n    const getCellClasses = (cell) => {\r\n      const classes: string[] = []\r\n      if ((cell.type === 'normal' || cell.type === 'today') && !cell.disabled) {\r\n        classes.push('available')\r\n        if (cell.type === 'today') {\r\n          classes.push('today')\r\n        }\r\n      } else {\r\n        classes.push(cell.type)\r\n      }\r\n\r\n      if (isCurrent(cell)) {\r\n        classes.push('current')\r\n      }\r\n\r\n      if (\r\n        cell.inRange &&\r\n        (cell.type === 'normal' ||\r\n          cell.type === 'today' ||\r\n          props.selectionMode === 'week')\r\n      ) {\r\n        classes.push('in-range')\r\n\r\n        if (cell.start) {\r\n          classes.push('start-date')\r\n        }\r\n\r\n        if (cell.end) {\r\n          classes.push('end-date')\r\n        }\r\n      }\r\n\r\n      if (cell.disabled) {\r\n        classes.push('disabled')\r\n      }\r\n\r\n      if (cell.selected) {\r\n        classes.push('selected')\r\n      }\r\n\r\n      if (cell.customClass) {\r\n        classes.push(cell.customClass)\r\n      }\r\n\r\n      return classes.join(' ')\r\n    }\r\n\r\n    const getDateOfCell = (row, column) => {\r\n      const offsetFromStart =\r\n        row * 7 + (column - (props.showWeekNumber ? 1 : 0)) - offsetDay.value\r\n      return startDate.value.add(offsetFromStart, 'day')\r\n    }\r\n\r\n    const handleMouseMove = (event) => {\r\n      if (!props.rangeState.selecting) return\r\n\r\n      let target = event.target\r\n      if (target.tagName === 'SPAN') {\r\n        target = target.parentNode.parentNode\r\n      }\r\n      if (target.tagName === 'DIV') {\r\n        target = target.parentNode\r\n      }\r\n      if (target.tagName !== 'TD') return\r\n\r\n      const row = target.parentNode.rowIndex - 1\r\n      const column = target.cellIndex\r\n\r\n      // can not select disabled date\r\n      if (rows.value[row][column].disabled) return\r\n\r\n      // only update rangeState when mouse moves to a new cell\r\n      // this avoids frequent Date object creation and improves performance\r\n      if (row !== lastRow.value || column !== lastColumn.value) {\r\n        lastRow.value = row\r\n        lastColumn.value = column\r\n        ctx.emit('changerange', {\r\n          selecting: true,\r\n          endDate: getDateOfCell(row, column),\r\n        })\r\n      }\r\n    }\r\n\r\n    const handleClick = (event) => {\r\n\r\n      let target = event.target\r\n\r\n      while (target) {\r\n        if (target.tagName === 'TD') {\r\n          break\r\n        }\r\n        target = target.parentNode\r\n      }\r\n\r\n      if (!target || target.tagName !== 'TD') return\r\n      const row = target.parentNode.rowIndex - 1\r\n      const column = target.cellIndex\r\n      const cell = rows.value[row][column]\r\n\r\n      if (cell.disabled || cell.type === 'week') return\r\n\r\n      const newDate = getDateOfCell(row, column)\r\n\r\n      if (props.selectionMode === 'range') {\r\n        if (!props.rangeState.selecting) {\r\n          ctx.emit('pick', { minDate: newDate, maxDate: null })\r\n          ctx.emit('select', true)\r\n        } else {\r\n          if (newDate >= props.minDate!) {\r\n            ctx.emit('pick', { minDate: props.minDate, maxDate: newDate })\r\n          } else {\r\n            ctx.emit('pick', { minDate: newDate, maxDate: props.minDate })\r\n          }\r\n          ctx.emit('select', false)\r\n        }\r\n      } else if (props.selectionMode === 'day') {\r\n        ctx.emit('pick', newDate)\r\n      } else if (props.selectionMode === 'week') {\r\n        const weekNumber = newDate.week()\r\n        const value = `${newDate.year()}w${weekNumber}`\r\n        ctx.emit('pick', {\r\n          year: newDate.year(),\r\n          week: weekNumber,\r\n          value,\r\n          date: newDate.startOf('week'),\r\n        })\r\n      } else if (props.selectionMode === 'dates') {\r\n        const newValue = cell.selected\r\n          ? coerceTruthyValueToArray(props.parsedValue).filter(\r\n              (_) => _.valueOf() !== newDate.valueOf()\r\n            )\r\n          : coerceTruthyValueToArray(props.parsedValue).concat([newDate])\r\n        ctx.emit('pick', newValue)\r\n      }\r\n    }\r\n\r\n    const isWeekActive = (cell) => {\r\n      if (props.selectionMode !== 'week') return false\r\n      let newDate = props.date!.startOf('day')\r\n\r\n      if (cell.type === 'prev-month') {\r\n        newDate = newDate.subtract(1, 'month')\r\n      }\r\n\r\n      if (cell.type === 'next-month') {\r\n        newDate = newDate.add(1, 'month')\r\n      }\r\n\r\n      newDate = newDate.date(parseInt(cell.text, 10))\r\n\r\n      if (props.parsedValue && !Array.isArray(props.parsedValue)) {\r\n        const dayOffset =\r\n          ((props.parsedValue.day() - firstDayOfWeek + 7) % 7) - 1\r\n        const weekDate = props.parsedValue.subtract(dayOffset, 'day')\r\n        return weekDate.isSame(newDate, 'day')\r\n      }\r\n      return false\r\n    }\r\n\r\n    return {\r\n      handleMouseMove,\r\n      t,\r\n      rows,\r\n      isWeekActive,\r\n      getCellClasses,\r\n      WEEKS,\r\n      handleClick,\r\n    }\r\n  },\r\n})\r\n</script>\r\n"],"names":["_resolveComponent","_openBlock","_createElementBlock","_createElementVNode","_toDisplayString","_createCommentVNode","_Fragment","_renderList","_normalizeClass"],"mappings":";;;;;;yCACEA,gBA8BQ,CAAA,qBAAA,CAAA,CAAA;SA5BNC,SAAe,EAAA,EAAAC,kBAAA,CAAA,OAAA,EAAA;AAAA,IACf,WAAK,EAAA,GAAA;AAAA,IAEJ,WAAK,EAAA,GAAA;AAAA,IACL,sBAAS,CAAE,eAAA,EAAA,EAAA,cAAA,EAAA,IAAA,CAAA,aAAA,KAAA,MAAA,EAAA,CAAA,CAAA;AAAA,IAAA,OAAA,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,WAAA,IAAA,IAAA,CAAA,WAAA,CAAA,GAAA,IAAA,CAAA,CAAA;IAEZ,WAqBQ,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,IAAA,CAAA,eAAA,IAAA,IAAA,CAAA,eAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,GAAA,EAAA;uBAnBM,OAAc,EAAA,IAAA,EAAA;AAAA,MAAxBC,kBAAA,CAAA,IAAA,EAAA,IAAA,EAAA;AAAA,QAAA,IAAA,CAAA,cAAA,IAAAF,SAAA,EAAA,EACAC,kBAEK,CAAA,IAAA,EAAA,UAAA,EAAAE,eAAA,CAFqB,IAAK,CAAA,CAAA,CAAnB,oBAAS,CAArB,CAAA,EAAA,CAAA,CAAA,IAAAC,kBAAA,CAAA,MAAA,EAAA,IAAA,CAAA;AAAA,SAAAJ,SAAA,CAAA,IAAA,CAAA,EAAAC,kBAAA,CAAAI,QAAA,EAAA,IAAA,EAAAC,UAAA,CAAA,IAAA,CAAA,KAAA,EAAA,CAAA,IAAA,EAAA,GAAA,KAAA;;AAIF,SAAA,CAAA,EAAA,GAAA,CAAA;AAAA,OAAA,CAAA;AAEW,OAAAN,SAAA,CAAA,IAAA,CAAA,EAAAC,kBAAA,CAAAI,QAAA,EAAA,IAAA,EAAAC,UAAA,CAAA,IAAA,CAAA,IAAA,EAAA,CAAA,GAAA,EAAA,GAAA,KAAA;AACJ,QAAA,OAAAN,SAAA,EAAA,EAAAC,kBAAA,CAAC,IAAoB,EAAA;AAAA,UAAA,GAAA;gCAG1B,CAMK,oBAAA,EAAA,EAAA,OAAA,EAAA,IAAA,CAAA,YAAA,CALK,GAAI,CAAA,CAAA,CAAE,CAAI,EAAA,CAAA,CAAA;AAAA,SAAA,EAAA;qBACZ,IAAI,CAAA,EAAAA,kBAAA,CAAAI,QAAA,EAAA,IAAA,EAAAC,UAAA,CAAA,GAAA,EAAA,CAAA,IAAA,EAAA,IAAA,KAAA;AACJ,YAAA,OAAAN,SAAA,EAAA,EAAAC,kBAAA,CAAE,IAAe,EAAA;AAAA,cAAA,GAAA,EAAA,IAAA;AAEvB,cAAA,KAAA,EAAAM,cAAA,CAAoC,IAAd,CAAA,cAAA,CAAA,IAAA,CAAA,CAAA;AAAA,aAAA,EAAA;;;;;;;;;;;;;"}