hongluan-ui
Version:
Hongluan Component Library for Vue 3
1 lines • 10.5 kB
Source Map (JSON)
{"version":3,"file":"basic-year-table.mjs","sources":["../../../../../../../packages/components/date-picker/src/date-picker-com/basic-year-table.vue"],"sourcesContent":["<template>\n <table\n role=\"grid\"\n :aria-label=\"t('hl.datepicker.yearTablePrompt')\"\n class=\"picker-table year-table\"\n @click=\"handleYearTableClick\"\n @mousemove=\"handleMouseMove\"\n >\n <tbody ref=\"tbodyRef\">\n <!-- <tr v-for=\"(_, i) in 3\" :key=\"i\">\n <template v-for=\"(__, j) in 4\" :key=\"i + '_' + j\">\n <td\n v-if=\"i * 4 + j < 10\"\n :ref=\"\n (el) =>\n isSelectedCell(startYear + i * 4 + j) && (currentCellRef = el)\n \"\n class=\"available\"\n :class=\"getCellKls(startYear + i * 4 + j)\"\n :aria-selected=\"`${isSelectedCell(startYear + i * 4 + j)}`\"\n :tabindex=\"isSelectedCell(startYear + i * 4 + j) ? 0 : -1\"\n @keydown.space.prevent.stop=\"handleYearTableClick\"\n @keydown.enter.prevent.stop=\"handleYearTableClick\"\n >\n <span class=\"cell\">{{ startYear + i * 4 + j }}</span>\n </td>\n <td v-else></td>\n </template>\n </tr> -->\n <tr v-for=\"(row, rowKey) in rows\" :key=\"rowKey\">\n <td\n v-for=\"(cell, cellKey) in row\"\n :key=\"`${rowKey}_${cellKey}`\"\n :ref=\"(el) => isSelectedCell(cell) && (currentCellRef = el)\"\n class=\"available\"\n :class=\"getCellKls(cell)\"\n :aria-selected=\"isSelectedCell(cell)\"\n :aria-label=\"String(cell.text)\"\n :tabindex=\"isSelectedCell(cell) ? 0 : -1\"\n @keydown.space.prevent.stop=\"handleYearTableClick\"\n @keydown.enter.prevent.stop=\"handleYearTableClick\"\n >\n <hl-date-picker-cell :cell=\"cell\" />\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 { rangeArr } from '@hongluan-ui/components/time-picker'\nimport { castArray, hasClass } from '@hongluan-ui/utils'\nimport { basicYearTableProps } from '../props/basic-year-table'\nimport HlDatePickerCell from './basic-cell-render'\nimport { getValidDateOfYear } from '../utils'\n\ntype YearCell = {\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 datesInYear = (year: number, lang: string) => {\n const firstDay = dayjs(String(year)).locale(lang).startOf('year')\n const lastDay = firstDay.endOf('year')\n const numOfDays = lastDay.dayOfYear()\n return rangeArr(numOfDays).map(n => firstDay.add(n, 'day').toDate())\n}\n\nconst props = defineProps(basicYearTableProps)\nconst emit = defineEmits(['changerange', 'pick', 'select'])\n\nconst { t, lang } = useLocale()\nconst tbodyRef = ref<HTMLElement>()\nconst currentCellRef = ref<HTMLElement>()\nconst startYear = computed(() => {\n return Math.floor(props.date.year() / 10) * 10\n})\n\nconst tableRows = ref<YearCell[][]>([[], [], []])\nconst lastRow = ref<number>()\nconst lastColumn = ref<number>()\nconst rows = computed(() => {\n const rows = tableRows.value\n const now = dayjs().locale(lang.value).startOf('year')\n\n for (let i = 0; i < 3; i++) {\n const row = rows[i]\n for (let j = 0; j < 4; j++) {\n if (i * 4 + j >= 10) {\n break\n }\n let cell = row[j]\n if (!cell) {\n cell = {\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 const index = i * 4 + j + startYear.value\n const calTime = dayjs().year(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, 'year') &&\n calEndDate &&\n calTime.isSameOrBefore(calEndDate, 'year')\n ) ||\n !!(\n props.minDate &&\n calTime.isSameOrBefore(props.minDate, 'year') &&\n calEndDate &&\n calTime.isSameOrAfter(calEndDate, 'year')\n )\n\n if (props.minDate?.isSameOrAfter(calEndDate)) {\n cell.start = !!(calEndDate && calTime.isSame(calEndDate, 'year'))\n cell.end = !!(props.minDate && calTime.isSame(props.minDate, 'year'))\n } else {\n cell.start = !!(props.minDate && calTime.isSame(props.minDate, 'year'))\n cell.end = !!(calEndDate && calTime.isSame(calEndDate, 'year'))\n }\n\n const isToday = now.isSame(calTime)\n if (isToday) {\n cell.type = 'today'\n }\n cell.text = index\n const cellDate = calTime.toDate()\n cell.disabled =\n (props.disabledDate && props.disabledDate(cellDate)) || false\n row[j] = cell\n }\n }\n return rows\n})\n\nconst focus = () => {\n currentCellRef.value?.focus()\n}\n\nconst getCellKls = (cell: YearCell) => {\n const kls: Record<string, boolean> = {}\n const today = dayjs().locale(lang.value)\n const year = cell.text\n\n kls.disabled = props.disabledDate\n ? datesInYear(year, lang.value).every(props.disabledDate)\n : false\n\n kls.today = today.year() === year\n kls.current =\n castArray(props.parsedValue).findIndex(d => d!.year() === year) >= 0\n\n if (cell.inRange) {\n kls['in-range'] = true\n\n if (cell.start) {\n kls['start-date'] = true\n }\n\n if (cell.end) {\n kls['end-date'] = true\n }\n }\n return kls\n}\n\nconst isSelectedCell = (cell: YearCell) => {\n const year = cell.text\n return castArray(props.date).findIndex(date => date.year() === year) >= 0\n}\n\nconst handleYearTableClick = (event: MouseEvent | KeyboardEvent) => {\n const target = (event.target as HTMLElement)?.closest(\n 'td',\n ) as HTMLTableCellElement\n if (!target || !target.textContent || hasClass(target, 'disabled')) return\n\n const column = target.cellIndex\n const row = (target.parentNode as HTMLTableRowElement).rowIndex\n const selectedYear = row * 4 + column + startYear.value\n const newDate = dayjs().year(selectedYear)\n 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 if (props.selectionMode === 'years') {\n if (event.type === 'keydown') {\n emit('pick', castArray(props.parsedValue), false)\n return\n }\n const vaildYear = getValidDateOfYear(\n newDate.startOf('year'),\n lang.value,\n props.disabledDate,\n )\n const newValue = hasClass(target, 'current')\n ? castArray(props.parsedValue).filter(d => d?.year() !== selectedYear)\n : castArray(props.parsedValue).concat([vaildYear])\n emit('pick', newValue)\n } else {\n emit('pick', selectedYear)\n }\n}\n\nconst handleMouseMove = (event: MouseEvent) => {\n if (!props.rangeState.selecting) return\n const target = (event.target as HTMLElement)?.closest(\n 'td',\n ) as HTMLTableCellElement\n if (!target) return\n\n const row = (target.parentNode as HTMLTableRowElement).rowIndex\n const column = (target as HTMLTableCellElement).cellIndex\n\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: dayjs()\n .year(startYear.value)\n .add(row * 4 + column, 'year'),\n })\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 on the current cell\n */\n focus,\n})\n</script>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAsEA,UAAM,cAAc,CAAC,MAAc,UAAiB;AAClD,YAAM,WAAW,MAAM,OAAO,IAAI,CAAC,EAAE,OAAO,KAAI,EAAE,QAAQ,MAAM;AAChE,YAAM,UAAU,SAAS,MAAM,MAAM;AACrC,YAAM,YAAY,QAAQ;AAC1B,aAAO,SAAS,SAAS,EAAE,IAAI,OAAK,SAAS,IAAI,GAAG,KAAK,EAAE,QAAQ;AAAA;AAMrE,UAAM,EAAE,GAAG,SAAS;AACpB,UAAM,WAAW;AACjB,UAAM,iBAAiB;AACvB,UAAM,YAAY,SAAS,MAAM;AAC/B,aAAO,KAAK,MAAM,MAAM,KAAK,SAAS,EAAE,IAAI;AAAA,KAC7C;AAED,UAAM,YAAY,IAAkB,CAAC,IAAI,IAAI,EAAE,CAAC;AAChD,UAAM,UAAU;AAChB,UAAM,aAAa;AACnB,UAAM,OAAO,SAAS,MAAM;AAC1B,YAAM;AACN,YAAM;AAEN,eAAS,WAAW;AAClB,oBAAY,MAAK;AACjB,iBAAS,WAAW;AAClB,kBAAQ,IAAI,SAAS;AACnB;AAAA;AAEF;AACA,cAAI,OAAO;AACT,mBAAO;AAAA,mBACA;AAAA,cACL;AAAQ,cACR,MAAM;AAAA,cACN;AAAS,cACT,OAAO;AAAA,cACP,KAAK;AAAA,cACL;AAAM,cACN;AAAU;AACZ;AAEF;AACA;AACA,gBAAM,gBAAgB;AAEtB,gBAAM,8BACa;AAKnB,0BACG,QACO,WACN,QAAQ;AAWZ,cAAI,uCAAuC;AACzC,iBAAK,QAAQ,CAAC,gBAAgB,QAAQ,OAAO;AAC7C,iBAAK,QAAS;AAAqD,iBAC9D;AACL,iBAAK;AACL,iBAAK,QAAS,gDAA+C;AAAA;AAG/D;AACA,uBAAa;AACX;AAAY;AAEd;AACA,2BAAiB;AACjB;AAEA,cAAI;AAAK;AACX;AAEF;AAAO;AAGT;AACE;AAA4B;AAG9B;AACE;AACA,oBAAc,QAAQ;AACtB,YAAM;AAEN,2BAAqB;AAIrB,wBAAkB,KAAK;AACvB,UAAI,yEAC4D;AAEhE,UAAI,KAAK,SAAS;AAChB;AAEA,wBAAgB;AACd,8BAAoB;AAAA,QACtB;AAEA;AACE;AAAkB,QACpB;AAAA;AAEF;AAAO;AAGT;AACE;AACA;AAAwE;AAG1E,iCAA6B,CAAC,UAAsC;AAClE;AAGA,UAAI,kCAAkC;AAA8B;AAEpE,YAAM,SAAS;AACf;AACA;AACA,YAAM,gBAAgB;AACtB;AACE,YAAI,kBAAkB;AACpB,kCAAwB;AACxB,eAAK,cAAc;AAAA,QACrB;AACE,cAAI;AACF,yBAAa;AAA4C;AAEzD,2BAAe;AAA0C;AAE3D;AAAoB;AACtB;AAEA;AACE;AACA;AAAA,QACF;AACA,cAAM,uCACI;AAIV;AAGA;AAAqB;AAErB,iCAAyB;AAAA;AAC3B;AAGF;AACE;AAAiC;AACjC;AAGA,UAAI;AAAS;AAEb;AACA,YAAM,SAAU;AAGhB,UAAI;AAAkC;AAItC,kBAAY,iBAAiB;AAC3B;AACA;AACA;AAAoB,UAClB;AAAW,2BAER;AAC4B,QACjC;AAAC;AACH;AAGF,UACE;AAEE,UAAI;AACF;AACA;AAA4B;AAC9B;AAIJ,WAAa;AAAA;AAIX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}