{"version":3,"file":"DatePicker-BfRcZg_q.js","sources":["../../src/assets/svgs/IconChevronLeft.svg?component","../../src/components/calendar/DatePicker.vue"],"sourcesContent":["import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nconst _hoisted_1 = {\n xmlns: \"http://www.w3.org/2000/svg\",\n fill: \"none\",\n viewBox: \"0 0 16 16\"\n}\n\nexport function render(_ctx, _cache) {\n return (_openBlock(), _createElementBlock(\"svg\", _hoisted_1, _cache[0] || (_cache[0] = [\n _createElementVNode(\"path\", { d: \"M10.273 11.053 7.22 8l3.053-3.06-.94-.94-4 4 4 4 .94-.947Z\" }, null, -1)\n ])))\n}\nexport default { render: render }","<template>\n <div\n v-if=\"sortedActiveDates\"\n ref=\"datepicker\"\n :class=\"[$style.datepicker, { [$style.embedded]: isEmbedded }]\"\n >\n <div :class=\"$style.inner\">\n <button\n v-if=\"props.collapsible\"\n aria-label=\"Close calendar\"\n :class=\"$style.close\"\n @click=\"$emit('close')\"\n >\n Close\n </button>\n <header :class=\"$style.header\">\n <button\n v-if=\"!isPrevMonthDisabled()\"\n aria-label=\"Previous Month\"\n :class=\"$style.prev\"\n @click=\"setMonth(-1)\"\n >\n <IconChevronLeft></IconChevronLeft>\n </button>\n <span aria-live=\"polite\" :class=\"$style.month\">\n {{ monthNames[currentMonthIndex] }} {{ currentYear }}\n </span>\n <button\n v-if=\"!isNextMonthDisabled()\"\n aria-label=\"Next Month\"\n :class=\"$style.next\"\n @click=\"setMonth(1)\"\n >\n <IconChevronRight></IconChevronRight>\n </button>\n </header>\n <div :class=\"$style.dates\">\n <span v-for=\"(day, key) in weekdays\" :key=\"key\" :class=\"$style.day\">{{ day }}</span>\n <component\n :is=\"isActiveDate(day) && day ? 'button' : 'span'\"\n v-for=\"(day, key) in currentMonthDays\"\n :key=\"key\"\n :aria-label=\"getLabel(day)\"\n :class=\"[\n (!isSelected(`${currentYear}-${currentMonth}-${pad(day)}`) || $style.selected,\n { [$style.active]: isActiveDate(day) }),\n $style.date,\n ]\"\n @click=\"!isActiveDate(day) || setCurrentDate(currentYear, currentMonthIndex, day)\"\n >\n {{ day }}\n </component>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { AppConfig } from '@/types/global.interface.ts';\nimport { computed, inject, onMounted, ref, watch } from 'vue';\nimport IconChevronLeft from '@/assets/svgs/IconChevronLeft.svg?component';\nimport IconChevronRight from '@/assets/svgs/IconChevronRight.svg?component';\nimport { monthNames } from '@/config/calendar';\n\nconst props = defineProps<{\n activeDates: string[];\n collapsible?: boolean;\n isEmbedded?: boolean;\n selectedDate: string;\n}>();\n\nconst appConfig = inject<AppConfig>('appConfig');\n\nconst emit = defineEmits(['close', 'update:selectedDate']);\n\nconst currentDate = ref<string>();\nconst currentDay = ref<string>();\nconst currentMonth = ref<string>();\nconst currentMonthDays = ref<string[]>([]);\nconst currentMonthIndex = ref<number>();\nconst currentYear = ref<number>();\nconst datepicker = ref(null);\nconst weekdays = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];\n\nconst sortedActiveDates = computed(() => {\n return undefined !== props.activeDates && props.activeDates.length\n ? props.activeDates.sort()\n : null;\n});\n\n// Set initial date when mounted, usually via URL param.\nonMounted(() => {\n setInitialDate(props.selectedDate);\n});\n\n// Watch selectedDate prop in case parent component updates it.\nwatch(\n () => props.selectedDate,\n (date) => {\n setInitialDate(date);\n },\n);\n\nwatch(currentMonthIndex, () => {\n currentMonth.value = ('00' + (currentMonthIndex.value + 1)).slice(-2);\n generateDays();\n});\n\n/**\n * Generates the days in the current month for rendering\n */\nfunction generateDays(): void {\n const firstDay = new Date(currentYear.value, currentMonthIndex.value, 1).getDay();\n const numDays = getNumberOfDays(currentYear.value, currentMonthIndex.value);\n\n currentMonthDays.value = [];\n\n if (firstDay) {\n // Prepend nulls to dates array to render days in correct position\n currentMonthDays.value = Array(firstDay).fill(null, firstDay);\n }\n\n for (let i = 0; i < numDays; i++) {\n const next = i + 1;\n currentMonthDays.value.push(next.toString());\n }\n}\n\nfunction getLabel(day: string): string {\n if (isActiveDate(day)) {\n return `${monthNames[currentMonthIndex.value]} ${day} ${currentYear.value}`;\n }\n}\n\nfunction getNumberOfDays(year: number, month: number): number {\n /*\n let tempMonth = currentMonthIndex.value;\n tempMonth = 11 === tempMonth ? 0 : tempMonth + 1;\n\n // Passing zero for the day returns days of the porevious month.\n return new Date(year, tempMonth, 0).getDate();\n */\n\n // See https://medium.com/swlh/build-a-date-picker-in-15mins-using-javascript-react-from-scratch-f6932c77db09#5e0a\n return 40 - new Date(year, month, 40).getDate();\n}\n\n/**\n * Conditionally checks, based on if active dates are passed as a prop,\n * whether or not the date is not in the past and active, is applicable.\n */\nfunction isActiveDate(day: string): boolean {\n if (sortedActiveDates.value) {\n return sortedActiveDates.value.indexOf(\n `${currentYear.value}-${currentMonth.value}-${pad(day)}`,\n ) > -1 && !isPastDate(day)\n ? true\n : false;\n }\n\n /*\n * Possible future support of enabling current and future dates.\n if (null === sortedActiveDates.value) {\n return !isPastDate(day) ? true : false;\n }\n */\n}\n\nfunction isNextMonthDisabled(): boolean {\n // Exit early if no active dates.\n if (null === sortedActiveDates.value) {\n return false;\n }\n\n // Active dates have zero-padded one-based index months\n const tempMonth = ('00' + (currentMonthIndex.value + 2)).slice(-2);\n const nextMonth = `${currentYear.value}-${tempMonth}-01`;\n\n // Disabled by default\n let resp = true;\n\n sortedActiveDates.value.forEach((activeDate) => {\n // Acts like break\n if (!resp) {\n return;\n }\n\n if (activeDate >= nextMonth) {\n resp = false;\n }\n });\n\n return resp;\n}\n\nfunction isPastDate(day): boolean {\n if (day) {\n return `${currentYear.value}-${currentMonth.value}-${pad(day)}` < appConfig.today.isoDate;\n }\n\n return true;\n}\n\nfunction isPrevMonthDisabled(): boolean {\n // Disable past months if no active dates are defined.\n if (null === sortedActiveDates.value) {\n let tempMonth = currentMonth.value;\n let tempYear = currentYear.value;\n\n if ('01' === tempMonth && appConfig.today.year === tempYear) {\n tempMonth = '12';\n tempYear--;\n }\n\n return `${tempYear}-${tempMonth}-01` < appConfig.today.isoDate;\n }\n\n // Check for an active date prior to the first of the month.\n if (sortedActiveDates.value) {\n const firstOfMonth = `${currentYear.value}-${currentMonth.value}-01`;\n\n // Disabled by default\n let resp = true;\n\n sortedActiveDates.value.forEach((activeDate) => {\n // Acts like break\n if (!resp) {\n return;\n }\n\n if (activeDate < firstOfMonth && activeDate >= appConfig.today.isoDate) {\n resp = false;\n }\n });\n\n return resp;\n }\n}\n\nfunction isSelected(date: string): boolean {\n return date === currentDate.value;\n}\n\nfunction pad(val: string): string {\n return ('00' + val).slice(-2);\n}\n\nfunction setCurrentDate(year: number, month: number, day: string): void {\n currentDay.value = pad(day);\n currentMonthIndex.value = month;\n currentYear.value = year;\n currentDate.value = `${currentYear.value}-${currentMonth.value}-${currentDay.value}`;\n\n emit('pick', currentDate.value);\n emit('update:selectedDate', currentDate.value);\n}\n\nfunction setInitialDate(date: string): void {\n let parts = null;\n\n if (date) {\n parts = date.split('-');\n currentDate.value = date;\n }\n\n if (!date && sortedActiveDates.value) {\n parts = sortedActiveDates.value[0].split('-');\n currentDate.value = sortedActiveDates.value[0];\n }\n\n if (parts) {\n currentDay.value = parts[2];\n currentMonthIndex.value = parts[1] - 1;\n currentYear.value = parts[0];\n }\n}\n\nfunction setMonth(inc: number): null {\n // Advancing past last month of the year.\n if (0 < inc && currentMonthIndex.value + inc === monthNames.length) {\n currentMonthIndex.value = 0;\n currentYear.value++;\n\n return;\n }\n\n // Advancing before last month of the year.\n if (0 < inc && currentMonthIndex.value + inc < monthNames.length) {\n currentMonthIndex.value++;\n\n return;\n }\n\n // Regressing before first month of the year.\n if (0 > inc && currentMonthIndex.value === 0) {\n currentMonthIndex.value = monthNames.length - 1;\n currentYear.value--;\n\n return;\n }\n\n // Regressing before first month of the year.\n if (0 > inc && 0 < currentMonthIndex.value) {\n currentMonthIndex.value--;\n\n return;\n }\n}\n</script>\n\n<style lang=\"scss\" module>\n.datepicker {\n background: $white;\n border: 1px solid $black;\n height: fit-content;\n max-width: px-to-rem(300);\n padding-bottom: 3.25rem;\n text-align: center;\n z-index: 100;\n\n button {\n color: inherit;\n font: inherit;\n line-height: normal;\n margin: 0;\n overflow: visible;\n padding: 0;\n text-decoration: none;\n width: auto;\n -webkit-font-smoothing: inherit;\n -moz-osx-font-smoothing: inherit;\n -webkit-appearance: none;\n\n &:focus {\n outline-width: 1px;\n }\n\n svg {\n display: inline-block;\n margin: 0;\n width: 1rem;\n }\n }\n\n header {\n display: grid;\n grid-template-columns: 32px 1fr 32px;\n grid-template-areas: 'prev month next';\n justify-content: center;\n padding: 1rem 1rem 0 1rem;\n }\n\n &.embedded {\n padding-bottom: 0;\n }\n\n .inner {\n position: relative;\n }\n\n .next,\n .prev {\n height: 1rem;\n width: 1rem;\n }\n\n .close {\n @include button-style;\n\n & {\n background-color: $black;\n bottom: -2.25rem;\n color: $white;\n font-size: 1rem;\n left: 0;\n right: 0;\n margin-left: auto;\n margin-right: auto;\n position: absolute;\n padding: 0.5rem 0;\n width: calc(100% - 32px);\n }\n\n &:focus {\n outline-width: 1px;\n }\n\n svg {\n margin-left: 0;\n }\n }\n\n .month {\n @include body-2;\n @include space-0-above;\n\n & {\n grid-area: month;\n }\n }\n\n .next {\n grid-area: next;\n margin-left: 1rem;\n }\n\n .prev {\n grid-area: prev;\n margin-right: 1rem;\n }\n\n .dates {\n display: grid;\n grid-template-columns: repeat(7, minmax(0, 1fr));\n row-gap: px-to-rem(5);\n padding: px-to-rem(5) 1rem 1rem 1rem;\n\n .day {\n @include heading-5;\n }\n\n button {\n background-color: $black;\n color: $white;\n\n &:hover {\n background-color: $black-hover;\n }\n\n &:active {\n background-color: $black-pressed;\n }\n\n &.selected {\n background-color: $black;\n\n &:hover {\n background-color: $black-hover;\n }\n\n &:active {\n background-color: $black-pressed;\n }\n }\n }\n\n span {\n background: transparent;\n }\n\n .date {\n @include body-2;\n\n & {\n align-items: center;\n border-radius: 50%;\n display: flex;\n height: 2rem;\n justify-content: center;\n width: 2rem;\n }\n }\n }\n}\n\n@media (min-width: $break-point) {\n .datepicker {\n .close {\n &:hover {\n text-decoration: underline;\n }\n }\n }\n}\n</style>\n"],"names":["_hoisted_1","render","_ctx","_cache","_openBlock","_createElementBlock","_createElementVNode","IconChevronLeft","props","__props","appConfig","inject","emit","__emit","currentDate","ref","currentDay","currentMonth","currentMonthDays","currentMonthIndex","currentYear","datepicker","weekdays","sortedActiveDates","computed","onMounted","setInitialDate","watch","date","generateDays","firstDay","numDays","getNumberOfDays","i","next","getLabel","day","isActiveDate","monthNames","year","month","pad","isPastDate","isNextMonthDisabled","tempMonth","nextMonth","resp","activeDate","isPrevMonthDisabled","tempYear","firstOfMonth","isSelected","val","setCurrentDate","parts","setMonth","inc"],"mappings":"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"}