{"version":3,"file":"basic-month-table.mjs","sources":["../../../../../../../packages/components/date-picker/src/date-picker-com/basic-month-table.vue"],"sourcesContent":["<template>\n  <table\n    role=\"grid\"\n    :aria-label=\"t('hl.datepicker.monthTablePrompt')\"\n    class=\"picker-table month-table\"\n    @click=\"handleMonthTableClick\"\n    @mousemove=\"handleMouseMove\"\n  >\n    <tbody ref=\"tbodyRef\">\n      <tr v-for=\"(row, key) in rows\" :key=\"key\">\n        <td\n          v-for=\"(cell, key_) in row\"\n          :key=\"key_\"\n          :ref=\"(el) => isSelectedCell(cell) && (currentCellRef = el)\"\n          :class=\"getCellStyle(cell)\"\n          :aria-selected=\"`${isSelectedCell(cell)}`\"\n          :aria-label=\"t(`hl.datepicker.month${+cell.text + 1}`)\"\n          :tabindex=\"isSelectedCell(cell) ? 0 : -1\"\n          @keydown.space.prevent.stop=\"handleMonthTableClick\"\n          @keydown.enter.prevent.stop=\"handleMonthTableClick\"\n        >\n          <hl-date-picker-cell\n            :cell=\"{\n              ...cell,\n              renderText: t('hl.datepicker.months.' + months[cell.text]),\n            }\"\n          />\n        </td>\n      </tr>\n    </tbody>\n  </table>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, nextTick, ref, watch } from 'vue'\nimport dayjs from 'dayjs'\nimport { useLocale } from '@hongluan-ui/hooks'\nimport { castArray, hasClass } from '@hongluan-ui/utils'\nimport { basicMonthTableProps } from '../props/basic-month-table'\nimport HlDatePickerCell from './basic-cell-render'\nimport { datesInMonth, getValidDateOfMonth } from '../utils'\n\ntype MonthCell = {\n  column: number\n  row: number\n  disabled: boolean\n  start: boolean\n  end: boolean\n  text: number\n  type: 'normal' | 'today'\n  inRange: boolean\n}\n\nconst props = defineProps(basicMonthTableProps)\nconst emit = defineEmits(['changerange', 'pick', 'select'])\n\nconst { t, lang } = useLocale()\nconst tbodyRef = ref<HTMLElement>()\nconst currentCellRef = ref<HTMLElement>()\nconst months = ref(\n  props.date\n    .locale('en')\n    .localeData()\n    .monthsShort()\n    .map(_ => _.toLowerCase()),\n)\nconst tableRows = ref<MonthCell[][]>([\n  [] as MonthCell[],\n  [] as MonthCell[],\n  [] as MonthCell[],\n])\nconst lastRow = ref<number>()\nconst lastColumn = ref<number>()\nconst rows = computed<MonthCell[][]>(() => {\n  const rows = tableRows.value\n\n  const now = dayjs().locale(lang.value).startOf('month')\n\n  for (let i = 0; i < 3; i++) {\n    const row = rows[i]\n    for (let j = 0; j < 4; j++) {\n      const cell = (row[j] ||= {\n        row: i,\n        column: j,\n        type: 'normal',\n        inRange: false,\n        start: false,\n        end: false,\n        text: -1,\n        disabled: false,\n      })\n\n      cell.type = 'normal'\n\n      const index = i * 4 + j\n      const calTime = props.date.startOf('year').month(index)\n\n      const calEndDate =\n        props.rangeState.endDate ||\n        props.maxDate ||\n        (props.rangeState.selecting && props.minDate) ||\n        null\n\n      cell.inRange =\n        !!(\n          props.minDate &&\n          calTime.isSameOrAfter(props.minDate, 'month') &&\n          calEndDate &&\n          calTime.isSameOrBefore(calEndDate, 'month')\n        ) ||\n        !!(\n          props.minDate &&\n          calTime.isSameOrBefore(props.minDate, 'month') &&\n          calEndDate &&\n          calTime.isSameOrAfter(calEndDate, 'month')\n        )\n\n      if (props.minDate?.isSameOrAfter(calEndDate)) {\n        cell.start = !!(calEndDate && calTime.isSame(calEndDate, 'month'))\n        cell.end = props.minDate && calTime.isSame(props.minDate, 'month')\n      } else {\n        cell.start = !!(props.minDate && calTime.isSame(props.minDate, 'month'))\n        cell.end = !!(calEndDate && calTime.isSame(calEndDate, 'month'))\n      }\n\n      const isToday = now.isSame(calTime)\n      if (isToday) {\n        cell.type = 'today'\n      }\n\n      cell.text = index\n      cell.disabled = props.disabledDate?.(calTime.toDate()) || false\n    }\n  }\n  return rows\n})\n\nconst focus = () => {\n  currentCellRef.value?.focus()\n}\n\nconst getCellStyle = (cell: MonthCell) => {\n  const style = {} as any\n  const year = props.date.year()\n  const today = new Date()\n  const month = cell.text\n\n  style.disabled = props.disabledDate\n    ? datesInMonth(year, month, lang.value).every(props.disabledDate)\n    : false\n  style.current =\n    castArray(props.parsedValue).findIndex(\n      date =>\n        dayjs.isDayjs(date) && date.year() === year && date.month() === month,\n    ) >= 0\n  style.today = today.getFullYear() === year && today.getMonth() === month\n\n  if (cell.inRange) {\n    style['in-range'] = true\n\n    if (cell.start) {\n      style['start-date'] = true\n    }\n\n    if (cell.end) {\n      style['end-date'] = true\n    }\n  }\n  return style\n}\n\nconst isSelectedCell = (cell: MonthCell) => {\n  const year = props.date.year()\n  const month = cell.text\n  return (\n    castArray(props.date).findIndex(\n      date => date.year() === year && date.month() === month,\n    ) >= 0\n  )\n}\n\nconst handleMouseMove = (event: MouseEvent) => {\n  if (!props.rangeState.selecting) return\n\n  let target = event.target as HTMLElement\n  if (target.tagName === 'SPAN') {\n    target = target.parentNode?.parentNode as HTMLElement\n  }\n  if (target.tagName === 'DIV') {\n    target = target.parentNode as HTMLElement\n  }\n  if (target.tagName !== 'TD') return\n\n  const row = (target.parentNode as HTMLTableRowElement).rowIndex\n  const column = (target as HTMLTableCellElement).cellIndex\n  // can not select disabled date\n  if (rows.value[row][column].disabled) return\n\n  // only update rangeState when mouse moves to a new cell\n  // this avoids frequent Date object creation and improves performance\n  if (row !== lastRow.value || column !== lastColumn.value) {\n    lastRow.value = row\n    lastColumn.value = column\n    emit('changerange', {\n      selecting: true,\n      endDate: props.date.startOf('year').month(row * 4 + column),\n    })\n  }\n}\nconst handleMonthTableClick = (event: MouseEvent | KeyboardEvent) => {\n  const target = (event.target as HTMLElement)?.closest(\n    'td',\n  ) as HTMLTableCellElement\n  if (target?.tagName !== 'TD') return\n  if (hasClass(target, 'disabled')) return\n  const column = target.cellIndex\n  const row = (target.parentNode as HTMLTableRowElement).rowIndex\n  const month = row * 4 + column\n  const newDate = props.date!.startOf('year').month(month)\n  if (props.selectionMode === 'months') {\n    if (event.type === 'keydown') {\n      emit('pick', castArray(props.parsedValue), false)\n      return\n    }\n    const newMonth = getValidDateOfMonth(\n      props.date.year(),\n      month,\n      lang.value,\n      props.disabledDate,\n    )\n\n    const newValue = hasClass(target, 'current')\n      ? castArray(props.parsedValue).filter(\n        d => d?.month() !== newMonth.month(),\n      )\n      : castArray(props.parsedValue).concat([dayjs(newMonth)])\n    emit('pick', newValue)\n  } else if (props.selectionMode === 'range') {\n    if (!props.rangeState.selecting) {\n      emit('pick', { minDate: newDate, maxDate: null })\n      emit('select', true)\n    } else {\n      if (props.minDate && newDate >= props.minDate) {\n        emit('pick', { minDate: props.minDate, maxDate: newDate })\n      } else {\n        emit('pick', { minDate: newDate, maxDate: props.minDate })\n      }\n      emit('select', false)\n    }\n  } else {\n    emit('pick', month)\n  }\n}\n\nwatch(\n  () => props.date,\n  async () => {\n    if (tbodyRef.value?.contains(document.activeElement)) {\n      await nextTick()\n      currentCellRef.value?.focus()\n    }\n  },\n)\n\ndefineExpose({\n  /**\n   * @description focus current cell\n   */\n  focus,\n})\n</script>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAwDA,UAAM,EAAE,GAAG,SAAS;AACpB,UAAM,WAAW;AACjB,UAAM,iBAAiB;AACvB,UAAM,SAAS,IACb,MAAM,KACH,OAAO,IAAI,EACX,aACA,cACA,IAAI,OAAK,EAAE,aAAa,CAC7B;AACA,UAAM,YAAY,IAAmB;AAAA,MACnC;AAAC,MACD;AAAC,MACD;AAAC,KACF;AACD,UAAM,UAAU;AAChB,UAAM,aAAa;AACnB,UAAM,OAAO,SAAwB,MAAM;AACzC,YAAM;AAEN,YAAM;AAEN,eAAS,WAAW;AAClB,oBAAY,MAAK;AACjB,iBAAS,WAAW;AAClB,kCAAyB;AAAA;AAClB,YACL;AAAQ,YACR,MAAM;AAAA,YACN;AAAS,YACT,OAAO;AAAA,YACP,KAAK;AAAA,YACL;AAAM,YACN;AAAU;AAGZ;AAEA;AACA,gBAAM,gBAAgB;AAEtB,gBAAM;AAMN,0BACG,QACO,WACN,QAAQ;AAWZ,cAAI,uCAAuC;AACzC,iBAAK,QAAQ,CAAC,gBAAgB,QAAQ,OAAO;AAC7C,iBAAK,4DAA4D;AAAA,iBAC5D;AACL,iBAAK;AACL,iBAAK,QAAS;AAAgD;AAGhE;AACA,uBAAa;AACX;AAAY;AAGd;AACA,eAAK;AAAqD;AAC5D;AAEF;AAAO;AAGT;AACE;AAA4B;AAG9B,0BAAsB;AACpB;AACA,yBAAmB,KAAK,KAAK;AAC7B,YAAM,QAAQ;AACd,YAAM,aAAa;AAEnB,YAAM;AAGN,YAAM;AAKN,YAAM,QAAQ,wBAAwB;AAEtC;AACE;AAEA,wBAAgB;AACd,gCAAsB;AAAA,QACxB;AAEA;AACE;AAAoB,QACtB;AAAA;AAEF;AAAO;AAGT;AACE;AACA;AACA,6BACkB;AAEX;AAIT,4BAAwB,CAAC;AACvB;AAAiC;AAEjC,UAAI;AACJ,UAAI,OAAO,oBAAoB;AAC7B;AAA4B,MAC9B;AACA,UAAI,OAAO,YAAY;AACrB,iBAAS;AAAO;AAElB,UAAI,OAAO,YAAY;AAAM;AAE7B;AACA;AAEA,eAAS;AAA6B;AAItC,kBAAY;AACV,wBAAgB;AAChB;AACA,aAAK;AAAe,qBACP;AAAA,mBACF;AAAiD,QAC5D;AAAC;AACH;AAEF,UAAM;AACJ;AAGA;AAA8B;AAC9B,UAAI;AAA8B;AAClC,qBAAe,OAAO;AACtB;AACA;AACA;AACA;AACE,YAAI,MAAM;AACR,uBAAa;AACb;AAAA;AAEF;AAOA,cAAM,qCAAqC;AAK3C;AAAqB;AAErB;AACE,yBAAe,SAAS,kBAAkB;AAC1C,6BAAmB;AAAA;AAEnB;AACE,yBAAa,mCAAmC;AAAS,UAC3D;AACE;AAAyD,UAC3D;AACA,yBAAe;AAAK;AACtB;AAEA;AAAkB;AACpB;AAGF;AAGI,mBAAa,OAAO;AAClB;AACA;AAA4B;AAC9B;AAIJ,WAAa;AAAA;AAIX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}