{"version":3,"file":"date-picker.cjs","names":[],"sources":["../src/inputs/date-picker/date-picker.ts"],"sourcesContent":["import { bind, define, getHost, html, onMounted, prop, ref, useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { format, Temporal } from '@vielzeug/tempo';\nimport {\n  createDatePickerControl,\n  createDropdownPositioner,\n  type DatePickerView,\n  formatDisplayDate,\n  parseIso,\n  toIsoString,\n} from '../../core';\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../shared';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './date-picker.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type OreDatePickerEvents = {\n  change: Event;\n  input: Event;\n};\n\nexport type OreDatePickerProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable the picker */\n  disabled?: boolean;\n  /** Validation error message */\n  error?: string;\n  /** Expand to container width */\n  fullwidth?: boolean;\n  /** Helper text below the field */\n  helper?: string;\n  /** Visible label */\n  label?: string;\n  /** Label placement */\n  'label-placement'?: 'inset' | 'outside';\n  /** Locale for day/month names (default: browser locale) */\n  locale?: string;\n  /** Latest selectable date in ISO 8601 format (yyyy-MM-dd) */\n  max?: string;\n  /** Earliest selectable date in ISO 8601 format (yyyy-MM-dd) */\n  min?: string;\n  /** Form field name */\n  name?: string;\n  /** Placeholder shown in the text trigger */\n  placeholder?: string;\n  /** Mark field as required */\n  required?: boolean;\n  /** Border radius */\n  rounded?: RoundedSize;\n  /** Component size */\n  size?: ComponentSize;\n  /**\n   * Shows an inline green check icon inside the field to confirm the value has\n   * passed validation. Ignored while `error` is set — an error always wins.\n   */\n  success?: boolean;\n  /**\n   * Selected date in ISO 8601 format (yyyy-MM-dd).\n   * @example '2025-06-15'\n   */\n  value?: string;\n  /** Visual variant */\n  variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n  /**\n   * Day-of-week indices to disable (0 = Sunday … 6 = Saturday).\n   * Pass as a JSON array attribute or a JS property.\n   * @example\n   * ```html\n   * <ore-date-picker weekend-days=\"[0,6]\"></ore-date-picker>\n   * ```\n   */\n  'weekend-days'?: number[];\n};\n\n/**\n * An accessible, keyboard-navigable date picker with an inline calendar popup.\n * Supports min/max bounds, disabled weekend days, and form association.\n *\n * @element ore-date-picker\n *\n * @attr {string} value - Selected date in ISO 8601 format (yyyy-MM-dd)\n * @attr {string} min - Minimum selectable date (yyyy-MM-dd)\n * @attr {string} max - Maximum selectable date (yyyy-MM-dd)\n * @attr {string} label - Label text\n * @attr {string} label-placement - 'inset' | 'outside'\n * @attr {string} placeholder - Trigger placeholder\n * @attr {boolean} disabled - Disable the picker\n * @attr {boolean} required - Required field\n * @attr {string} name - Form field name\n * @attr {string} error - Error message\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} helper - Helper text\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - Component size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string} rounded - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string} locale - BCP 47 locale string\n * @attr {string} weekend-days - Comma-separated day indices to disable\n *\n * @fires input - Fired when a date is selected.\n * @fires change - Fired when a date is selected.\n *\n * @slot label - Custom label for the trigger field\n * @slot prefix - Content before the trigger text (e.g. icon)\n * @slot helper - Custom helper text\n * @slot error - Custom error content\n *\n * @cssprop --date-picker-bg - Calendar background\n * @cssprop --date-picker-border-color - Calendar border color\n * @cssprop --date-picker-radius - Calendar border radius\n * @cssprop --date-picker-day-selected-bg - Background of selected day\n * @cssprop --date-picker-day-today-color - Color of today's date number\n * @cssprop --date-picker-day-outside-opacity - Opacity of days outside visible month\n *\n * @part field - The trigger button/field\n * @part calendar - The floating calendar panel\n * @part header - Calendar header (nav + label)\n * @part grid - Day grid\n * @part day - Individual day cell\n *\n * @example\n * ```html\n * <!-- Single date with constraints -->\n * <ore-date-picker label=\"Appointment date\" name=\"date\" min=\"2025-01-01\" max=\"2025-12-31\" color=\"primary\"></ore-date-picker>\n *\n *\n * <!-- Outside label, bordered variant -->\n * <ore-date-picker label=\"Start date\" label-placement=\"outside\" variant=\"bordered\"></ore-date-picker>\n * ```\n */\nexport const DATE_PICKER_TAG = 'ore-date-picker' as const;\n\ndefine<OreDatePickerProps>(DATE_PICKER_TAG, {\n  formAssociated: true,\n  props: {\n    ...themableBundle,\n    ...sizableBundle,\n    ...disablableBundle,\n    ...roundableBundle,\n    error: prop.string(),\n    fullwidth: prop.bool(false),\n    helper: prop.string(),\n    label: prop.string(),\n    'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n    locale: prop.string(),\n    max: prop.string(),\n    min: prop.string(),\n    name: prop.string(),\n    placeholder: prop.string(),\n    required: prop.bool(false),\n    success: prop.bool(false),\n    value: prop.string(),\n    variant: prop.string<'flat' | 'solid' | 'bordered' | 'outline' | 'ghost'>(),\n    'weekend-days': prop.json([] as number[]),\n  },\n\n  setup(props) {\n    const el = getHost();\n\n    // ── Signals ─────────────────────────────────────────────────────────────\n\n    const isOpen = signal(false);\n\n    // ── Selected date: local-override pattern ──────────────────────────────\n    // localSelection holds a user-initiated pick (or undefined = no override).\n    // selectedDate falls back to the value prop reactively — no setInterval needed.\n\n    const localSelection = signal<Temporal.PlainDate | null | undefined>(undefined);\n\n    const selectedDate = computed(() =>\n      localSelection.value !== undefined ? localSelection.value : parseIso(props.value.value),\n    );\n\n    defineFieldValue(\n      el,\n      () => toIsoString(selectedDate.value) ?? '',\n      (value) => {\n        localSelection.value = parseIso(value);\n      },\n    );\n\n    const isDisabled = computed(() => Boolean(props.disabled.value));\n    const locale = computed(() => props.locale.value || (typeof navigator !== 'undefined' ? navigator.language : 'en'));\n\n    // ── Date-picker control ─────────────────────────────────────────────────\n\n    const ctrl = createDatePickerControl({\n      get locale() {\n        return locale.value;\n      },\n      get max() {\n        return parseIso(props.max.value);\n      },\n      get min() {\n        return parseIso(props.min.value);\n      },\n      onChange(date) {\n        localSelection.value = date;\n        isOpen.value = false;\n        ctrl.setView('day');\n        currentView.value = 'day';\n        displayYear.value = ctrl.displayYear();\n        displayMonth.value = ctrl.displayMonth();\n        setFieldValue(el, toIsoString(date) ?? '');\n        dispatchNativeFieldEvent(el, 'input');\n        dispatchNativeFieldEvent(el, 'change');\n      },\n      get value() {\n        return selectedDate.value;\n      },\n      get weekendDays() {\n        return props['weekend-days'].value ?? [];\n      },\n    });\n\n    // ── Reactive display state ────────────────────────────────────────────\n    // Three separate primitive signals — the proven pattern.\n\n    const currentView = signal<DatePickerView>('day');\n    const displayYear = signal(ctrl.displayYear());\n    const displayMonth = signal(ctrl.displayMonth()); // 1-indexed (Temporal)\n\n    // ── Form value (host is formAssociated) ──────────────────────────────────\n\n    useField<string>({\n      disabled: isDisabled,\n      toFormValue: (v) => v || null,\n      value: computed(() => toIsoString(selectedDate.value) ?? ''),\n    });\n\n    const dialogId = `date-picker-${Math.random().toString(36).slice(2, 9)}-calendar`;\n\n    // ── Floating position ────────────────────────────────────────────────────\n    // The old CSS-only `position: absolute; top: 100%` positioned the calendar relative to\n    // the host box — fine until the host sits near a scroll/clip ancestor's edge (e.g. a form\n    // grid inside a dialog), where the same absolute box also expands that ancestor's\n    // *scrollable* overflow area even though it never changes the ancestor's own layout size,\n    // which reads as \"the dialog got bigger\"/jumped. `createDropdownPositioner` — the same\n    // Orbit-powered primitive `ore-select`'s dropdown already uses — positions via `fixed` +\n    // computed `top`/`left`, auto-detecting both the nearest clipping ancestor (so flip/shift\n    // keep the calendar within the dialog panel, not just the page viewport) and any ancestor\n    // that establishes a containing block for `position: fixed` (a dialog panel's entrance\n    // transition commonly leaves a permanent, if visually-identity, `transform` at rest) —\n    // see `createDropdownPositioner`'s own `boundary`/`containingBlock` docs.\n    const triggerRef = ref<HTMLElement>();\n    const calendarRef = ref<HTMLElement>();\n\n    const positioner = createDropdownPositioner({\n      getFloating: () => calendarRef.value ?? null,\n      getReference: () => triggerRef.value ?? null,\n      matchWidth: false,\n      offsetPx: 4,\n    });\n\n    let stopAutoUpdate: (() => void) | null = null;\n\n    // ── Derived display values ───────────────────────────────────────────────\n\n    const triggerText = computed(() => {\n      if (selectedDate.value) return formatDisplayDate(selectedDate.value, locale.value);\n\n      return props.placeholder.value || '';\n    });\n\n    const displayMonth_ = computed(() => {\n      const d = Temporal.PlainDate.from({ day: 1, month: displayMonth.value, year: displayYear.value });\n\n      return format(d, { intl: { month: 'long' }, locale: locale.value, timeZone: 'UTC' });\n    });\n\n    const displayYear_ = computed(() => String(displayYear.value));\n    const displayLabel = computed(() => `${displayMonth_.value} ${displayYear_.value}`);\n\n    const dayCells = computed(() => {\n      void displayYear.value;\n      void displayMonth.value;\n      void selectedDate.value; // re-run when selection changes to refresh isSelected flags\n\n      return ctrl.dayCells();\n    });\n    const monthCells = computed(() => {\n      void displayYear.value;\n\n      return ctrl.monthCells();\n    });\n    const yearCells = computed(() => {\n      void displayYear.value;\n\n      return ctrl.yearCells();\n    });\n    const weekdayLabels = computed(() => ctrl.weekdayLabels());\n    const tabIndex = () => (isDisabled.value ? '-1' : '0');\n\n    // ── Navigation handlers ──────────────────────────────────────────────────\n    // In year/month views navigate by year; in day view navigate by month.\n\n    function handlePrev(): void {\n      if (currentView.value === 'day') ctrl.prevMonth();\n      else ctrl.prevYear();\n\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n    }\n\n    function handleNext(): void {\n      if (currentView.value === 'day') ctrl.nextMonth();\n      else ctrl.nextYear();\n\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n    }\n\n    function handleHeaderClick(): void {\n      const views: DatePickerView[] = ['day', 'month', 'year'];\n      const next = views[(views.indexOf(currentView.value) + 1) % views.length];\n\n      ctrl.setView(next);\n      currentView.value = next;\n    }\n\n    function handleSelectMonth(month: number): void {\n      ctrl.goTo(ctrl.displayYear(), month);\n      ctrl.setView('day');\n      displayYear.value = ctrl.displayYear();\n      displayMonth.value = ctrl.displayMonth();\n      currentView.value = 'day';\n    }\n\n    function handleSelectYear(year: number): void {\n      ctrl.goTo(year, ctrl.displayMonth());\n      ctrl.setView('month');\n      displayYear.value = ctrl.displayYear();\n      currentView.value = 'month';\n    }\n\n    function handleSelectDay(isoStr: string): void {\n      const date = parseIso(isoStr);\n\n      if (!date) return;\n\n      ctrl.select(date);\n    }\n\n    function handleDayKeydown(e: KeyboardEvent): void {\n      const cell = e.currentTarget as HTMLElement;\n      const grid = cell.closest('.cal-grid-days');\n\n      if (!grid) return;\n\n      const allCells = Array.from(grid.querySelectorAll<HTMLElement>('.cal-cell-day'));\n      const idx = allCells.indexOf(cell);\n\n      if (idx === -1) return;\n\n      let target: HTMLElement | undefined;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        handleSelectDay(cell.dataset.iso ?? '');\n\n        return;\n      } else if (e.key === 'ArrowRight') {\n        target = allCells[idx + 1];\n      } else if (e.key === 'ArrowLeft') {\n        target = allCells[idx - 1];\n      } else if (e.key === 'ArrowDown') {\n        target = allCells[idx + 7];\n      } else if (e.key === 'ArrowUp') {\n        target = allCells[idx - 7];\n      } else if (e.key === 'Home') {\n        target = allCells[Math.floor(idx / 7) * 7];\n      } else if (e.key === 'End') {\n        target = allCells[Math.floor(idx / 7) * 7 + 6];\n      } else {\n        return;\n      }\n\n      e.preventDefault();\n      target?.focus();\n    }\n\n    // ── Month/year-cell keyboard navigation (fixed 4-column grid) ─────────────\n\n    function handleGridKeydown(e: KeyboardEvent, cellSelector: string, columns: number, onSelect: () => void): void {\n      const cell = e.currentTarget as HTMLElement;\n      const grid = cell.closest('.cal-grid');\n\n      if (!grid) return;\n\n      const allCells = Array.from(grid.querySelectorAll<HTMLElement>(cellSelector));\n      const idx = allCells.indexOf(cell);\n\n      if (idx === -1) return;\n\n      let target: HTMLElement | undefined;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        onSelect();\n\n        return;\n      } else if (e.key === 'ArrowRight') {\n        target = allCells[idx + 1];\n      } else if (e.key === 'ArrowLeft') {\n        target = allCells[idx - 1];\n      } else if (e.key === 'ArrowDown') {\n        target = allCells[idx + columns];\n      } else if (e.key === 'ArrowUp') {\n        target = allCells[idx - columns];\n      } else if (e.key === 'Home') {\n        target = allCells[Math.floor(idx / columns) * columns];\n      } else if (e.key === 'End') {\n        target = allCells[Math.min(Math.floor(idx / columns) * columns + columns - 1, allCells.length - 1)];\n      } else {\n        return;\n      }\n\n      e.preventDefault();\n      target?.focus();\n    }\n\n    // ── Open / close ─────────────────────────────────────────────────────────\n\n    function openPicker(): void {\n      if (isDisabled.value) return;\n\n      isOpen.value = true;\n      ctrl.setView('day');\n      currentView.value = 'day';\n\n      const sel = selectedDate.value;\n\n      if (sel) {\n        ctrl.goTo(sel.year, sel.month);\n        displayYear.value = ctrl.displayYear();\n        displayMonth.value = ctrl.displayMonth();\n      }\n\n      positioner.update();\n      stopAutoUpdate = positioner.startAutoUpdate?.() ?? null;\n    }\n\n    function closePicker(): void {\n      isOpen.value = false;\n      ctrl.setView('day');\n      currentView.value = 'day';\n      stopAutoUpdate?.();\n      stopAutoUpdate = null;\n    }\n\n    function handleTriggerClick(): void {\n      if (isOpen.value) closePicker();\n      else openPicker();\n    }\n\n    // ── Keyboard handlers ────────────────────────────────────────────────────\n\n    function handleTriggerKeydown(e: KeyboardEvent): void {\n      if (isDisabled.value) return;\n\n      if (e.key === 'Enter' || e.key === ' ') {\n        e.preventDefault();\n        handleTriggerClick();\n      } else if (e.key === 'Escape' && isOpen.value) {\n        e.preventDefault();\n        closePicker();\n      }\n    }\n\n    function handleCalendarKeydown(e: KeyboardEvent): void {\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        closePicker();\n      }\n    }\n\n    function handleOutsideClick(e: PointerEvent | MouseEvent): void {\n      if (!isOpen.value) return;\n\n      const path = e.composedPath();\n\n      if (!path.includes(el)) closePicker();\n    }\n\n    // ── Lifecycle ────────────────────────────────────────────────────────────\n\n    onMounted(() => {\n      document.addEventListener('pointerdown', handleOutsideClick, { capture: true });\n\n      return () => {\n        document.removeEventListener('pointerdown', handleOutsideClick, { capture: true });\n        stopAutoUpdate?.();\n        stopAutoUpdate = null;\n      };\n    });\n\n    // ── Host bindings ────────────────────────────────────────────────────────\n\n    bind({\n      attr: {\n        open: () => (isOpen.value ? true : undefined),\n      },\n    });\n\n    // ── Template ─────────────────────────────────────────────────────────────\n\n    const inputValue = () => triggerText.value;\n    const inputLabel = () => props.label.value ?? '';\n    const inputPlaceholder = () => props.placeholder.value ?? '';\n    const inputLabelPlacement = () => props['label-placement'].value ?? 'inset';\n    const inputColor = () => props.color?.value ?? undefined;\n    const inputSize = () => props.size?.value ?? undefined;\n    const inputVariant = () => props.variant?.value ?? undefined;\n    const inputRounded = () => props.rounded?.value ?? undefined;\n    const inputHelper = () => props.helper.value ?? '';\n    const inputError = () => props.error.value ?? '';\n    const inputDisabled = () => (isDisabled.value ? true : undefined);\n    const inputRequired = () => (props.required.value ? true : undefined);\n    const inputFullwidth = () => (props.fullwidth.value ? true : undefined);\n\n    return html`\n      <!-- Trigger: ore-input in readonly display mode -->\n      <ore-input\n        class=\"trigger\"\n        ref=\"${triggerRef}\"\n        readonly\n        tabindex=\"${tabIndex}\"\n        role=\"combobox\"\n        aria-haspopup=\"dialog\"\n        aria-controls=\"${dialogId}\"\n        aria-expanded=\"${() => String(isOpen.value)}\"\n        aria-disabled=\"${() => (isDisabled.value ? 'true' : null)}\"\n        value=\"${inputValue}\"\n        label=\"${inputLabel}\"\n        placeholder=\"${inputPlaceholder}\"\n        label-placement=\"${inputLabelPlacement}\"\n        color=\"${inputColor}\"\n        size=\"${inputSize}\"\n        variant=\"${inputVariant}\"\n        rounded=\"${inputRounded}\"\n        helper=\"${inputHelper}\"\n        error=\"${inputError}\"\n        ?disabled=\"${inputDisabled}\"\n        ?required=\"${inputRequired}\"\n        ?fullwidth=\"${inputFullwidth}\"\n        ?success=\"${() => props.success.value}\"\n        @click=\"${handleTriggerClick}\"\n        @keydown=\"${handleTriggerKeydown}\">\n        <ore-icon slot=\"suffix\" name=\"calendar\" size=\"16\" stroke-width=\"1.75\" aria-hidden=\"true\"></ore-icon>\n      </ore-input>\n\n      <!-- Calendar popup -->\n      <div\n        class=\"calendar\"\n        ref=\"${calendarRef}\"\n        id=\"${dialogId}\"\n        role=\"dialog\"\n        aria-modal=\"true\"\n        aria-label=\"${() => `Choose date — ${displayLabel.value}`}\"\n        ?data-open=\"${isOpen}\"\n        @keydown=\"${handleCalendarKeydown}\">\n        <!-- Calendar header -->\n        <div class=\"cal-header\" part=\"header\">\n          <button class=\"nav-btn\" type=\"button\" aria-label=\"Previous\" @click=\"${handlePrev}\">\n            <ore-icon name=\"chevron-left\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </button>\n          <button\n            class=\"cal-label-btn\"\n            type=\"button\"\n            aria-label=\"${() =>\n              `Switch to ${currentView.value === 'day' ? 'month' : currentView.value === 'month' ? 'year' : 'day'} view`}\"\n            @click=\"${handleHeaderClick}\">\n            <span class=\"cal-label-month\">${displayMonth_}</span>\n            <span class=\"cal-label-sep\" aria-hidden=\"true\">/</span>\n            <span class=\"cal-label-year\">${displayYear_}</span>\n          </button>\n          <button class=\"nav-btn\" type=\"button\" aria-label=\"Next\" @click=\"${handleNext}\">\n            <ore-icon name=\"chevron-right\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n          </button>\n        </div>\n\n        <!-- Day view: flat 7-column CSS grid, weekday headers + day cells -->\n        <div\n          class=\"cal-grid cal-grid-days\"\n          role=\"grid\"\n          part=\"grid\"\n          aria-label=\"${() => displayLabel.value}\"\n          ?hidden=\"${() => currentView.value !== 'day'}\">\n          <div role=\"row\" class=\"cal-grid-row\">\n            ${() =>\n              weekdayLabels.value.map(\n                (lbl) => html`\n                  <div class=\"cal-cell cal-cell-head\" role=\"columnheader\" aria-label=\"${lbl}\">${lbl}</div>\n                `,\n              )}\n          </div>\n          ${() => {\n            const cells = dayCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 7) rows.push(cells.slice(i, i + 7));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\" class=\"cal-grid-row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-day\"\n                        role=\"gridcell\"\n                        part=\"day\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled)}\"\n                        aria-current=\"${() => (cell.isToday ? 'date' : null)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-today=\"${() => cell.isToday}\"\n                        ?data-outside=\"${() => cell.isOutsideMonth}\"\n                        ?data-disabled=\"${() => cell.isDisabled}\"\n                        data-iso=\"${cell.iso}\"\n                        tabindex=\"${() => (cell.isDisabled ? '-1' : '0')}\"\n                        @click=\"${() => handleSelectDay(cell.iso)}\"\n                        @keydown=\"${handleDayKeydown}\">\n                        ${String(cell.day)}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n\n        <!-- Month view -->\n        <div\n          class=\"cal-grid cal-grid-months\"\n          role=\"grid\"\n          aria-label=\"${() => displayYear_.value}\"\n          ?hidden=\"${() => currentView.value !== 'month'}\">\n          ${() => {\n            const cells = monthCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 4) rows.push(cells.slice(i, i + 4));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-month\"\n                        role=\"gridcell\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-disabled=\"${() => cell.isDisabled}\"\n                        tabindex=\"${() => (cell.isDisabled ? '-1' : '0')}\"\n                        @click=\"${() => {\n                          if (!cell.isDisabled) handleSelectMonth(cell.month);\n                        }}\"\n                        @keydown=\"${(e: KeyboardEvent) =>\n                          handleGridKeydown(e, '.cal-cell-month', 4, () => {\n                            if (!cell.isDisabled) handleSelectMonth(cell.month);\n                          })}\">\n                        ${cell.shortLabel}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n\n        <!-- Year view -->\n        <div\n          class=\"cal-grid cal-grid-years\"\n          role=\"grid\"\n          aria-label=\"Select year\"\n          ?hidden=\"${() => currentView.value !== 'year'}\">\n          ${() => {\n            const cells = yearCells.value;\n            const rows: (typeof cells)[number][][] = [];\n\n            for (let i = 0; i < cells.length; i += 4) rows.push(cells.slice(i, i + 4));\n\n            return rows.map(\n              (row) => html`\n                <div role=\"row\">\n                  ${row.map(\n                    (cell) => html`\n                      <div\n                        class=\"cal-cell cal-cell-year\"\n                        role=\"gridcell\"\n                        aria-selected=\"${() => String(cell.isSelected)}\"\n                        aria-disabled=\"${() => String(cell.isDisabled)}\"\n                        ?data-selected=\"${() => cell.isSelected}\"\n                        ?data-disabled=\"${() => cell.isDisabled}\"\n                        tabindex=\"${() => (cell.isDisabled ? '-1' : '0')}\"\n                        @click=\"${() => {\n                          if (!cell.isDisabled) handleSelectYear(cell.year);\n                        }}\"\n                        @keydown=\"${(e: KeyboardEvent) =>\n                          handleGridKeydown(e, '.cal-cell-year', 4, () => {\n                            if (!cell.isDisabled) handleSelectYear(cell.year);\n                          })}\">\n                        ${String(cell.year)}\n                      </div>\n                    `,\n                  )}\n                </div>\n              `,\n            );\n          }}\n        </div>\n      </div>\n    `;\n  },\n\n  shadow: { delegatesFocus: true },\n  styles: [colorThemeMixin, reducedMotionMixin, componentStyles],\n});\n"],"mappings":"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"}