{"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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"}