calkit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +734 -0
- package/dist/booking.es.js +1845 -0
- package/dist/booking.es.js.map +1 -0
- package/dist/booking.umd.js +888 -0
- package/dist/booking.umd.js.map +1 -0
- package/dist/calkit.es.js +5230 -0
- package/dist/calkit.es.js.map +1 -0
- package/dist/calkit.umd.js +2164 -0
- package/dist/calkit.umd.js.map +1 -0
- package/dist/datepicker.es.js +1619 -0
- package/dist/datepicker.es.js.map +1 -0
- package/dist/datepicker.umd.js +818 -0
- package/dist/datepicker.umd.js.map +1 -0
- package/dist/scheduler.es.js +3235 -0
- package/dist/scheduler.es.js.map +1 -0
- package/dist/scheduler.umd.js +1547 -0
- package/dist/scheduler.umd.js.map +1 -0
- package/dist/timepicker.es.js +962 -0
- package/dist/timepicker.es.js.map +1 -0
- package/dist/timepicker.umd.js +517 -0
- package/dist/timepicker.umd.js.map +1 -0
- package/llms.txt +594 -0
- package/package.json +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"booking.umd.js","sources":["../src/core/base-component.js","../src/core/state.js","../src/core/dates.js","../src/core/times.js","../src/styles/tokens.js","../src/styles/reset.js","../src/styles/animations.js","../src/components/datepicker/navigation.js","../src/components/datepicker/month-year-picker.js","../src/components/datepicker/popover.js","../src/components/booking/booking-data.js","../src/components/datepicker/calendar-grid.js","../src/components/timepicker/time-grid.js","../src/components/shared/loading-skeleton.js","../src/components/shared/status-message.js","../src/components/booking/index.js","../src/entries/booking.js"],"sourcesContent":["/**\n * Shared base class for all calendar web components.\n * Provides Shadow DOM setup, style injection, render lifecycle, and helpers.\n */\nexport class CalendarBase extends HTMLElement {\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n this._initialized = false;\n }\n\n /** Override in subclass — return array of CSSStyleSheet or CSS strings. */\n static get styles() {\n return [];\n }\n\n connectedCallback() {\n if (!this._initialized) {\n this._adoptStyles();\n this._initialized = true;\n }\n this.render();\n }\n\n _adoptStyles() {\n const sheets = this.constructor.styles;\n if (!sheets.length) return;\n\n // Try constructable stylesheets first\n if ('adoptedStyleSheets' in this.shadowRoot) {\n this.shadowRoot.adoptedStyleSheets = sheets.map((s) => {\n if (s instanceof CSSStyleSheet) return s;\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(s);\n return sheet;\n });\n } else {\n // Fallback: inject <style> tags\n for (const s of sheets) {\n const el = document.createElement('style');\n el.textContent = s instanceof CSSStyleSheet ? '' : s;\n this.shadowRoot.prepend(el);\n }\n }\n }\n\n /** Subclasses override to update Shadow DOM. */\n render() {}\n\n /** Dispatch a composed, bubbling custom event. */\n emit(name, detail = {}) {\n this.dispatchEvent(\n new CustomEvent(name, { detail, bubbles: true, composed: true })\n );\n }\n\n /** Show an inline status banner. */\n showStatus(type, message, opts = {}) {\n if (!this._store) return;\n const { autoDismiss, dismissible = true } = opts;\n clearTimeout(this._statusTimer);\n this._store.set({ statusType: type, statusMessage: message, statusDismissible: dismissible });\n this.emit('cal:status', { type, message });\n if (autoDismiss && autoDismiss > 0) {\n this._statusTimer = setTimeout(() => this.clearStatus(), autoDismiss);\n }\n }\n\n /** Clear the status banner. */\n clearStatus() {\n if (!this._store) return;\n clearTimeout(this._statusTimer);\n this._store.set({ statusType: null, statusMessage: null, statusDismissible: true });\n this.emit('cal:status', { type: null, message: null });\n }\n\n /** Query within shadow root. */\n $(selector) {\n return this.shadowRoot.querySelector(selector);\n }\n\n $$(selector) {\n return this.shadowRoot.querySelectorAll(selector);\n }\n}\n","/**\n * Minimal pub/sub reactive store.\n * Usage:\n * const store = createStore({ count: 0 });\n * store.subscribe((state) => console.log(state.count));\n * store.set({ count: 1 });\n */\nexport function createStore(initial) {\n let state = { ...initial };\n const listeners = new Set();\n\n return {\n get(key) {\n return state[key];\n },\n\n set(partial) {\n const prev = state;\n state = { ...state, ...partial };\n // Only notify if something actually changed\n let changed = false;\n for (const key of Object.keys(partial)) {\n if (prev[key] !== state[key]) {\n changed = true;\n break;\n }\n }\n if (changed) {\n for (const fn of listeners) fn(state, prev);\n }\n },\n\n getState() {\n return state;\n },\n\n subscribe(fn) {\n listeners.add(fn);\n return () => listeners.delete(fn);\n },\n };\n}\n","export const MONTH_NAMES = [\n 'January', 'February', 'March', 'April', 'May', 'June',\n 'July', 'August', 'September', 'October', 'November', 'December',\n];\n\nconst SHORT_WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];\nconst DAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\nconst SHORT_DAY_NAMES = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n\n/**\n * Get the full or short day name for a date string.\n * @param {string} dateStr - ISO date string\n * @param {'long'|'short'} format\n * @returns {string}\n */\nexport function getDayName(dateStr, format = 'short') {\n const d = parseDate(dateStr);\n if (!d) return '';\n return format === 'long' ? DAY_NAMES[d.getDay()] : SHORT_DAY_NAMES[d.getDay()];\n}\n\n/**\n * Returns weekday labels starting from `firstDay` (0 = Sunday).\n */\nexport function getWeekdayLabels(firstDay = 0) {\n const labels = [];\n for (let i = 0; i < 7; i++) {\n labels.push(SHORT_WEEKDAYS[(firstDay + i) % 7]);\n }\n return labels;\n}\n\nexport function getDaysInMonth(year, month) {\n return new Date(year, month + 1, 0).getDate();\n}\n\nexport function getFirstDayOfMonth(year, month) {\n return new Date(year, month, 1).getDay();\n}\n\n/** Returns \"YYYY-MM-DD\" string for a Date or {year, month, day}. */\nexport function toDateString(date) {\n if (typeof date === 'string') return date;\n const d = date instanceof Date ? date : new Date(date.year, date.month, date.day);\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n}\n\n/** Parse an ISO date string or Date into a Date object at midnight local. */\nexport function parseDate(value) {\n if (!value) return null;\n if (value instanceof Date) return value;\n if (typeof value === 'string') {\n const [y, m, d] = value.split('-').map(Number);\n if (!y || !m || !d) return null;\n return new Date(y, m - 1, d);\n }\n return null;\n}\n\nexport function isSameDay(a, b) {\n if (!a || !b) return false;\n const da = parseDate(a);\n const db = parseDate(b);\n if (!da || !db) return false;\n return da.getFullYear() === db.getFullYear()\n && da.getMonth() === db.getMonth()\n && da.getDate() === db.getDate();\n}\n\nexport function isInRange(date, start, end) {\n if (!date || !start || !end) return false;\n const d = parseDate(date);\n const s = parseDate(start);\n const e = parseDate(end);\n if (!d || !s || !e) return false;\n const dt = d.getTime();\n const st = Math.min(s.getTime(), e.getTime());\n const et = Math.max(s.getTime(), e.getTime());\n return dt >= st && dt <= et;\n}\n\nexport function isBefore(a, b) {\n const da = parseDate(a);\n const db = parseDate(b);\n if (!da || !db) return false;\n return da.getTime() < db.getTime();\n}\n\nexport function isAfter(a, b) {\n const da = parseDate(a);\n const db = parseDate(b);\n if (!da || !db) return false;\n return da.getTime() > db.getTime();\n}\n\nexport function today() {\n return toDateString(new Date());\n}\n\nexport function addMonths(year, month, delta) {\n const d = new Date(year, month + delta, 1);\n return { year: d.getFullYear(), month: d.getMonth() };\n}\n\n/**\n * Checks if two date ranges overlap.\n * When allowSameDay=true, checkout/checkin on same day is NOT treated as overlap.\n */\nexport function rangesOverlap(startA, endA, startB, endB, allowSameDay = false) {\n if (!startA || !endA || !startB || !endB) return false;\n if (allowSameDay) {\n return startA < endB && endA > startB;\n }\n return startA <= endB && endA >= startB;\n}\n\n/** Returns ISO date string offset by N days. */\nexport function addDays(dateStr, n) {\n const d = parseDate(dateStr);\n if (!d) return dateStr;\n d.setDate(d.getDate() + n);\n return toDateString(d);\n}\n\n/** Returns array of all ISO date strings in range (inclusive). */\nexport function getDateRange(start, end) {\n const result = [];\n const s = parseDate(start);\n const e = parseDate(end);\n if (!s || !e) return result;\n const current = new Date(s);\n while (current <= e) {\n result.push(toDateString(current));\n current.setDate(current.getDate() + 1);\n }\n return result;\n}\n\n/**\n * Build a 42-cell (6×7) grid for the given month.\n * Each cell: { year, month, day, dateString, isCurrentMonth, isToday }\n * `firstDay` = 0 (Sun) .. 6 (Sat).\n */\nexport function buildMonthGrid(year, month, firstDay = 0) {\n const daysInMonth = getDaysInMonth(year, month);\n const rawStartDay = getFirstDayOfMonth(year, month);\n const startOffset = (rawStartDay - firstDay + 7) % 7;\n const cells = [];\n const todayStr = today();\n\n // Previous month fill\n const prev = addMonths(year, month, -1);\n const daysInPrev = getDaysInMonth(prev.year, prev.month);\n for (let i = startOffset - 1; i >= 0; i--) {\n const day = daysInPrev - i;\n const dateString = toDateString({ year: prev.year, month: prev.month, day });\n cells.push({ year: prev.year, month: prev.month, day, dateString, isCurrentMonth: false, isToday: dateString === todayStr });\n }\n\n // Current month\n for (let day = 1; day <= daysInMonth; day++) {\n const dateString = toDateString({ year, month, day });\n cells.push({ year, month, day, dateString, isCurrentMonth: true, isToday: dateString === todayStr });\n }\n\n // Next month fill\n const next = addMonths(year, month, 1);\n let i = 1;\n while (cells.length < 42) {\n const dateString = toDateString({ year: next.year, month: next.month, day: i });\n cells.push({ year: next.year, month: next.month, day: i, dateString, isCurrentMonth: false, isToday: dateString === todayStr });\n i++;\n }\n\n return cells;\n}\n","/**\n * Time utility functions for the time picker component.\n */\n\n/**\n * Parse a time string into { hours, minutes }.\n * Handles \"09:00\", \"9:00 AM\", \"14:30\", \"2:30 PM\".\n */\nexport function parseTime(str) {\n if (!str || typeof str !== 'string') return null;\n const trimmed = str.trim().toUpperCase();\n const ampmMatch = trimmed.match(/^(\\d{1,2}):(\\d{2})\\s*(AM|PM)$/);\n if (ampmMatch) {\n let hours = parseInt(ampmMatch[1], 10);\n const minutes = parseInt(ampmMatch[2], 10);\n const period = ampmMatch[3];\n if (period === 'AM' && hours === 12) hours = 0;\n if (period === 'PM' && hours !== 12) hours += 12;\n return { hours, minutes };\n }\n const match24 = trimmed.match(/^(\\d{1,2}):(\\d{2})$/);\n if (match24) {\n return { hours: parseInt(match24[1], 10), minutes: parseInt(match24[2], 10) };\n }\n return null;\n}\n\n/**\n * Format hours/minutes into a display string.\n * @param {number} hours\n * @param {number} minutes\n * @param {'12h'|'24h'} format\n */\nexport function formatTime(hours, minutes, format = '24h') {\n const mm = String(minutes).padStart(2, '0');\n if (format === '12h') {\n const period = hours >= 12 ? 'PM' : 'AM';\n const h = hours % 12 || 12;\n return `${h}:${mm} ${period}`;\n }\n return `${String(hours).padStart(2, '0')}:${mm}`;\n}\n\n/** Convert a time string (HH:MM or h:MM AM/PM) to minutes since midnight. */\nexport function timeToMinutes(str) {\n const t = parseTime(str);\n if (!t) return 0;\n return t.hours * 60 + t.minutes;\n}\n\n/** Convert minutes since midnight back to \"HH:MM\". */\nexport function minutesToTime(n) {\n const hours = Math.floor(n / 60) % 24;\n const minutes = n % 60;\n return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;\n}\n\n/**\n * Generate time slots between start and end times.\n * @param {string} startTime - e.g. \"09:00\"\n * @param {string} endTime - e.g. \"17:00\"\n * @param {number} intervalMinutes - e.g. 30\n * @returns {string[]} - e.g. [\"09:00\", \"09:30\", \"10:00\", ...]\n */\nexport function generateSlots(startTime, endTime, intervalMinutes) {\n const slots = [];\n const startMin = timeToMinutes(startTime);\n const endMin = timeToMinutes(endTime);\n for (let m = startMin; m <= endMin; m += intervalMinutes) {\n slots.push(minutesToTime(m));\n }\n return slots;\n}\n\n/**\n * Generate time slots with duration labels (e.g. \"09:00–09:30\").\n * @param {string} startTime - e.g. \"09:00\"\n * @param {string} endTime - e.g. \"17:00\"\n * @param {number} intervalMinutes - e.g. 30\n * @param {'12h'|'24h'} format\n * @returns {Array<{time: string, displayText: string}>}\n */\nexport function generateDurationSlots(startTime, endTime, intervalMinutes, format = '24h') {\n const slots = [];\n const startMin = timeToMinutes(startTime);\n const endMin = timeToMinutes(endTime);\n for (let m = startMin; m <= endMin; m += intervalMinutes) {\n const time = minutesToTime(m);\n const nextMin = m + intervalMinutes;\n const endSlotTime = minutesToTime(Math.min(nextMin, endMin + intervalMinutes));\n const parsed = parseTime(time);\n const parsedEnd = parseTime(endSlotTime);\n const fromText = parsed ? formatTime(parsed.hours, parsed.minutes, format) : time;\n const toText = parsedEnd ? formatTime(parsedEnd.hours, parsedEnd.minutes, format) : endSlotTime;\n slots.push({ time, displayText: `${fromText}\\u2013${toText}` });\n }\n return slots;\n}\n\n/** Returns true if time A is strictly before time B. */\nexport function isTimeBefore(a, b) {\n return timeToMinutes(a) < timeToMinutes(b);\n}\n\n/**\n * Check if two time ranges overlap (exclusive boundaries).\n * @param {string} startA - \"HH:MM\"\n * @param {string} endA - \"HH:MM\"\n * @param {string} startB - \"HH:MM\"\n * @param {string} endB - \"HH:MM\"\n * @returns {boolean}\n */\nexport function timeRangesOverlap(startA, endA, startB, endB) {\n const a0 = timeToMinutes(startA);\n const a1 = timeToMinutes(endA);\n const b0 = timeToMinutes(startB);\n const b1 = timeToMinutes(endB);\n return a0 < b1 && a1 > b0;\n}\n\n/**\n * Get the current time as \"HH:MM\".\n * @returns {string}\n */\nexport function currentTime() {\n const now = new Date();\n return `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;\n}\n\n/** Returns true if time is within [start, end] inclusive. */\nexport function isTimeInRange(time, start, end) {\n const t = timeToMinutes(time);\n const s = timeToMinutes(start);\n const e = timeToMinutes(end);\n const lo = Math.min(s, e);\n const hi = Math.max(s, e);\n return t >= lo && t <= hi;\n}\n","export const tokens = `\n :host {\n /* Light theme (default) */\n --cal-bg: 0 0% 100%;\n --cal-bg-muted: 240 5% 96%;\n --cal-fg: 240 6% 10%;\n --cal-fg-muted: 240 4% 46%;\n --cal-border: 240 6% 90%;\n --cal-accent: 240 6% 10%;\n --cal-accent-fg: 0 0% 100%;\n --cal-accent-subtle: 240 5% 96%;\n --cal-hover: 240 5% 93%;\n --cal-ring: 240 6% 10%;\n --cal-radius: 8px;\n --cal-radius-sm: 6px;\n --cal-cell-size: 36px;\n --cal-transition: 150ms ease;\n\n /* Booking color palette (softer / less saturated) */\n --cal-booking-blue-bg: 217 55% 94%;\n --cal-booking-blue-fg: 217 60% 35%;\n --cal-booking-green-bg: 152 45% 93%;\n --cal-booking-green-fg: 152 55% 28%;\n --cal-booking-red-bg: 4 50% 94%;\n --cal-booking-red-fg: 4 55% 40%;\n --cal-booking-orange-bg: 30 55% 93%;\n --cal-booking-orange-fg: 30 60% 35%;\n --cal-booking-gray-bg: 240 8% 94%;\n --cal-booking-gray-fg: 240 8% 38%;\n\n /* Booking hover tokens */\n --cal-booking-blue-hover: 217 55% 88%;\n --cal-booking-green-hover: 152 45% 87%;\n --cal-booking-red-hover: 4 50% 88%;\n --cal-booking-orange-hover: 30 55% 87%;\n --cal-booking-gray-hover: 240 8% 88%;\n\n /* Scheduler tokens */\n --cal-sched-grid-line: 240 6% 94%;\n --cal-sched-now-line: 4 70% 55%;\n --cal-sched-slot-hover: 240 5% 97%;\n --cal-sched-header-bg: 240 5% 98%;\n\n /* Status tokens */\n --cal-status-error-bg: 4 50% 95%;\n --cal-status-error-fg: 4 55% 40%;\n --cal-status-error-border: 4 50% 85%;\n --cal-status-warning-bg: 40 55% 95%;\n --cal-status-warning-fg: 40 60% 35%;\n --cal-status-warning-border: 40 50% 85%;\n --cal-status-info-bg: 217 55% 95%;\n --cal-status-info-fg: 217 60% 35%;\n --cal-status-info-border: 217 50% 85%;\n --cal-status-success-bg: 152 45% 95%;\n --cal-status-success-fg: 152 55% 28%;\n --cal-status-success-border: 152 45% 85%;\n }\n\n :host([theme=\"dark\"]) {\n --cal-bg: 240 6% 10%;\n --cal-bg-muted: 240 4% 16%;\n --cal-fg: 0 0% 98%;\n --cal-fg-muted: 240 4% 54%;\n --cal-border: 240 4% 20%;\n --cal-accent: 0 0% 98%;\n --cal-accent-fg: 240 6% 10%;\n --cal-accent-subtle: 240 4% 16%;\n --cal-hover: 240 4% 20%;\n --cal-ring: 0 0% 98%;\n\n --cal-booking-blue-bg: 217 50% 25%;\n --cal-booking-blue-fg: 217 80% 75%;\n --cal-booking-green-bg: 142 40% 22%;\n --cal-booking-green-fg: 142 70% 70%;\n --cal-booking-red-bg: 4 45% 25%;\n --cal-booking-red-fg: 4 70% 75%;\n --cal-booking-orange-bg: 30 45% 25%;\n --cal-booking-orange-fg: 30 80% 75%;\n --cal-booking-gray-bg: 240 5% 22%;\n --cal-booking-gray-fg: 240 5% 65%;\n\n --cal-booking-blue-hover: 217 50% 30%;\n --cal-booking-green-hover: 142 40% 27%;\n --cal-booking-red-hover: 4 45% 30%;\n --cal-booking-orange-hover: 30 45% 30%;\n --cal-booking-gray-hover: 240 5% 27%;\n\n --cal-sched-grid-line: 240 4% 18%;\n --cal-sched-now-line: 4 55% 55%;\n --cal-sched-slot-hover: 240 4% 14%;\n --cal-sched-header-bg: 240 5% 12%;\n\n --cal-status-error-bg: 4 45% 20%;\n --cal-status-error-fg: 4 70% 75%;\n --cal-status-error-border: 4 45% 30%;\n --cal-status-warning-bg: 40 45% 20%;\n --cal-status-warning-fg: 40 80% 75%;\n --cal-status-warning-border: 40 45% 30%;\n --cal-status-info-bg: 217 50% 20%;\n --cal-status-info-fg: 217 80% 75%;\n --cal-status-info-border: 217 50% 30%;\n --cal-status-success-bg: 152 40% 18%;\n --cal-status-success-fg: 152 70% 70%;\n --cal-status-success-border: 152 40% 28%;\n }\n\n :host([theme=\"auto\"]) {\n --cal-bg: 0 0% 100%;\n --cal-bg-muted: 240 5% 96%;\n --cal-fg: 240 6% 10%;\n --cal-fg-muted: 240 4% 46%;\n --cal-border: 240 6% 90%;\n --cal-accent: 240 6% 10%;\n --cal-accent-fg: 0 0% 100%;\n --cal-accent-subtle: 240 5% 96%;\n --cal-hover: 240 5% 93%;\n --cal-ring: 240 6% 10%;\n }\n\n @media (prefers-color-scheme: dark) {\n :host([theme=\"auto\"]) {\n --cal-bg: 240 6% 10%;\n --cal-bg-muted: 240 4% 16%;\n --cal-fg: 0 0% 98%;\n --cal-fg-muted: 240 4% 54%;\n --cal-border: 240 4% 20%;\n --cal-accent: 0 0% 98%;\n --cal-accent-fg: 240 6% 10%;\n --cal-accent-subtle: 240 4% 16%;\n --cal-hover: 240 4% 20%;\n --cal-ring: 0 0% 98%;\n\n --cal-booking-blue-bg: 217 50% 25%;\n --cal-booking-blue-fg: 217 80% 75%;\n --cal-booking-green-bg: 142 40% 22%;\n --cal-booking-green-fg: 142 70% 70%;\n --cal-booking-red-bg: 4 45% 25%;\n --cal-booking-red-fg: 4 70% 75%;\n --cal-booking-orange-bg: 30 45% 25%;\n --cal-booking-orange-fg: 30 80% 75%;\n --cal-booking-gray-bg: 240 5% 22%;\n --cal-booking-gray-fg: 240 5% 65%;\n\n --cal-booking-blue-hover: 217 50% 30%;\n --cal-booking-green-hover: 142 40% 27%;\n --cal-booking-red-hover: 4 45% 30%;\n --cal-booking-orange-hover: 30 45% 30%;\n --cal-booking-gray-hover: 240 5% 27%;\n\n --cal-sched-grid-line: 240 4% 18%;\n --cal-sched-now-line: 4 55% 55%;\n --cal-sched-slot-hover: 240 4% 14%;\n --cal-sched-header-bg: 240 5% 12%;\n\n --cal-status-error-bg: 4 45% 20%;\n --cal-status-error-fg: 4 70% 75%;\n --cal-status-error-border: 4 45% 30%;\n --cal-status-warning-bg: 40 45% 20%;\n --cal-status-warning-fg: 40 80% 75%;\n --cal-status-warning-border: 40 45% 30%;\n --cal-status-info-bg: 217 50% 20%;\n --cal-status-info-fg: 217 80% 75%;\n --cal-status-info-border: 217 50% 30%;\n --cal-status-success-bg: 152 40% 18%;\n --cal-status-success-fg: 152 70% 70%;\n --cal-status-success-border: 152 40% 28%;\n }\n }\n`;\n","export const reset = `\n :host {\n display: inline-block;\n font-family: inherit;\n font-size: 14px;\n line-height: 1.5;\n color: hsl(var(--cal-fg));\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n :host([display=\"inline\"]) {\n display: inline-block;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n button {\n font: inherit;\n color: inherit;\n background: none;\n border: none;\n padding: 0;\n margin: 0;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n button:focus-visible {\n outline: 2px solid hsl(var(--cal-ring));\n outline-offset: 2px;\n border-radius: var(--cal-radius-sm);\n }\n\n [hidden] {\n display: none !important;\n }\n`;\n","export const animations = `\n @keyframes cal-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes cal-slide-up {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes cal-slide-left {\n from {\n opacity: 0;\n transform: translateX(16px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n }\n\n @keyframes cal-slide-right {\n from {\n opacity: 0;\n transform: translateX(-16px);\n }\n to {\n opacity: 1;\n transform: translateX(0);\n }\n }\n\n .cal-animate-fade { animation: cal-fade-in 150ms cubic-bezier(0.16, 1, 0.3, 1); }\n .cal-animate-slide-up { animation: cal-slide-up 200ms cubic-bezier(0.16, 1, 0.3, 1); }\n .cal-animate-slide-left { animation: cal-slide-left 200ms cubic-bezier(0.16, 1, 0.3, 1); }\n .cal-animate-slide-right { animation: cal-slide-right 200ms cubic-bezier(0.16, 1, 0.3, 1); }\n\n @keyframes cal-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n\n .cal-skeleton {\n background: linear-gradient(\n 90deg,\n hsl(var(--cal-bg-muted)) 25%,\n hsl(var(--cal-hover)) 50%,\n hsl(var(--cal-bg-muted)) 75%\n );\n background-size: 200% 100%;\n animation: cal-shimmer 1.5s infinite ease-in-out;\n border-radius: 999px;\n }\n\n .cal-skeleton--rect {\n border-radius: var(--cal-radius-sm);\n }\n`;\n","import { MONTH_NAMES } from '../../core/dates.js';\n\nexport const chevronLeft = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M10 12L6 8l4-4\"/></svg>`;\nexport const chevronRight = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6 4l4 4-4 4\"/></svg>`;\n\n/**\n * Renders month/year navigation header.\n * @param {object} options\n * @param {number} options.year\n * @param {number} options.month\n * @param {function} options.onPrev\n * @param {function} options.onNext\n * @param {function} [options.onTitleClick] - If provided, title becomes a clickable button\n * @returns {HTMLElement}\n */\nexport function renderNavigation({ year, month, onPrev, onNext, onTitleClick }) {\n const nav = document.createElement('div');\n nav.classList.add('cal-nav');\n\n const prevBtn = document.createElement('button');\n prevBtn.classList.add('cal-nav__btn', 'cal-nav__btn--prev');\n prevBtn.innerHTML = chevronLeft;\n prevBtn.setAttribute('aria-label', 'Previous month');\n prevBtn.addEventListener('click', onPrev);\n\n const titleTag = onTitleClick ? 'button' : 'div';\n const title = document.createElement(titleTag);\n title.classList.add('cal-nav__title');\n if (onTitleClick) {\n title.classList.add('cal-nav__title--interactive');\n title.setAttribute('aria-label', `Select month and year, currently ${MONTH_NAMES[month]} ${year}`);\n title.addEventListener('click', onTitleClick);\n }\n title.setAttribute('aria-live', 'polite');\n title.textContent = `${MONTH_NAMES[month]} ${year}`;\n\n const nextBtn = document.createElement('button');\n nextBtn.classList.add('cal-nav__btn', 'cal-nav__btn--next');\n nextBtn.innerHTML = chevronRight;\n nextBtn.setAttribute('aria-label', 'Next month');\n nextBtn.addEventListener('click', onNext);\n\n nav.appendChild(prevBtn);\n nav.appendChild(title);\n nav.appendChild(nextBtn);\n\n return nav;\n}\n\nexport const navigationStyles = `\n .cal-nav {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 4px;\n margin-bottom: 8px;\n }\n\n .cal-nav__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border-radius: var(--cal-radius-sm);\n color: hsl(var(--cal-fg));\n transition: background var(--cal-transition);\n }\n\n .cal-nav__btn:hover {\n background: hsl(var(--cal-hover));\n }\n\n .cal-nav__title {\n font-size: 14px;\n font-weight: 600;\n color: hsl(var(--cal-fg));\n user-select: none;\n }\n\n .cal-nav__title--interactive {\n cursor: pointer;\n padding: 2px 8px;\n border-radius: var(--cal-radius-sm);\n transition: background var(--cal-transition);\n }\n\n .cal-nav__title--interactive:hover {\n background: hsl(var(--cal-hover));\n }\n`;\n","import { chevronLeft, chevronRight } from './navigation.js';\n\nconst SHORT_MONTHS = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\n];\n\n/**\n * Renders a month/year quick-select picker (3×4 month grid with year arrows).\n * @param {object} options\n * @param {number} options.pickerYear - Year displayed in the picker\n * @param {number} options.viewMonth - Currently viewed month (0-11)\n * @param {number} options.viewYear - Currently viewed year\n * @param {function} options.onMonthSelect - (month, year) => void\n * @param {function} options.onYearPrev - Go to previous year\n * @param {function} options.onYearNext - Go to next year\n * @param {function} options.onClose - Close the picker\n * @returns {HTMLElement}\n */\nexport function renderMonthYearPicker({\n pickerYear, viewMonth, viewYear,\n onMonthSelect, onYearPrev, onYearNext, onClose,\n}) {\n const wrapper = document.createElement('div');\n wrapper.classList.add('cal-myp', 'cal-animate-fade');\n\n // Year navigation row\n const yearNav = document.createElement('div');\n yearNav.classList.add('cal-myp__year-nav');\n\n const prevBtn = document.createElement('button');\n prevBtn.classList.add('cal-nav__btn');\n prevBtn.innerHTML = chevronLeft;\n prevBtn.setAttribute('aria-label', 'Previous year');\n prevBtn.addEventListener('click', onYearPrev);\n\n const yearLabel = document.createElement('div');\n yearLabel.classList.add('cal-myp__year-label');\n yearLabel.textContent = pickerYear;\n\n const nextBtn = document.createElement('button');\n nextBtn.classList.add('cal-nav__btn');\n nextBtn.innerHTML = chevronRight;\n nextBtn.setAttribute('aria-label', 'Next year');\n nextBtn.addEventListener('click', onYearNext);\n\n yearNav.appendChild(prevBtn);\n yearNav.appendChild(yearLabel);\n yearNav.appendChild(nextBtn);\n wrapper.appendChild(yearNav);\n\n // 3×4 month grid\n const grid = document.createElement('div');\n grid.classList.add('cal-myp__grid');\n\n const now = new Date();\n const todayMonth = now.getMonth();\n const todayYear = now.getFullYear();\n\n for (let m = 0; m < 12; m++) {\n const cell = document.createElement('button');\n cell.classList.add('cal-myp__cell');\n cell.textContent = SHORT_MONTHS[m];\n\n // Currently viewed month\n if (m === viewMonth && pickerYear === viewYear) {\n cell.classList.add('cal-myp__cell--active');\n }\n\n // Real current month (today)\n if (m === todayMonth && pickerYear === todayYear) {\n cell.classList.add('cal-myp__cell--today');\n }\n\n cell.addEventListener('click', () => onMonthSelect(m, pickerYear));\n grid.appendChild(cell);\n }\n\n wrapper.appendChild(grid);\n\n // Escape key\n wrapper.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onClose();\n }\n });\n\n return wrapper;\n}\n\nexport const monthYearPickerStyles = `\n .cal-myp {\n width: calc(7 * var(--cal-cell-size));\n }\n\n .cal-myp__year-nav {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 4px;\n margin-bottom: 8px;\n }\n\n .cal-myp__year-label {\n font-size: 14px;\n font-weight: 600;\n color: hsl(var(--cal-fg));\n user-select: none;\n }\n\n .cal-myp__grid {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 4px;\n }\n\n .cal-myp__cell {\n display: flex;\n align-items: center;\n justify-content: center;\n height: calc(var(--cal-cell-size) * 1.5);\n font-size: 13px;\n font-weight: 500;\n color: hsl(var(--cal-fg));\n border-radius: var(--cal-radius-sm);\n cursor: pointer;\n transition: background var(--cal-transition);\n user-select: none;\n }\n\n .cal-myp__cell:hover {\n background: hsl(var(--cal-hover));\n }\n\n .cal-myp__cell--active {\n background: hsl(var(--cal-accent));\n color: hsl(var(--cal-accent-fg));\n font-weight: 600;\n }\n\n .cal-myp__cell--active:hover {\n background: hsl(var(--cal-accent));\n }\n\n .cal-myp__cell--today:not(.cal-myp__cell--active) {\n border: 1px solid hsl(var(--cal-border));\n font-weight: 600;\n }\n`;\n","/**\n * Creates a popover panel anchored to a trigger element.\n * @param {object} options\n * @param {HTMLElement} options.trigger - the element that opens the popover\n * @param {HTMLElement} options.content - the popover body\n * @param {function} options.onClose\n * @returns {{ panel: HTMLElement, open: function, close: function, destroy: function }}\n */\nexport function createPopover({ trigger, content, onClose }) {\n const panel = document.createElement('div');\n panel.classList.add('cal-popover');\n panel.setAttribute('role', 'dialog');\n panel.setAttribute('aria-modal', 'false');\n panel.style.display = 'none';\n panel.appendChild(content);\n\n let isOpen = false;\n\n function position() {\n // Reset position classes\n panel.classList.remove('cal-popover--above');\n\n const triggerRect = trigger.getBoundingClientRect();\n const panelHeight = panel.offsetHeight;\n const spaceBelow = window.innerHeight - triggerRect.bottom;\n const spaceAbove = triggerRect.top;\n\n // Prefer below, flip above if not enough space\n if (spaceBelow < panelHeight + 8 && spaceAbove > spaceBelow) {\n panel.classList.add('cal-popover--above');\n panel.style.top = 'auto';\n panel.style.bottom = '100%';\n panel.style.marginBottom = '4px';\n panel.style.marginTop = '0';\n } else {\n panel.style.top = '100%';\n panel.style.bottom = 'auto';\n panel.style.marginTop = '4px';\n panel.style.marginBottom = '0';\n }\n }\n\n function open() {\n if (isOpen) return;\n isOpen = true;\n panel.style.display = '';\n panel.classList.add('cal-animate-slide-up');\n // Measure after display\n requestAnimationFrame(() => position());\n document.addEventListener('click', outsideClick, true);\n document.addEventListener('keydown', escapeKey, true);\n }\n\n function close() {\n if (!isOpen) return;\n isOpen = false;\n panel.style.display = 'none';\n panel.classList.remove('cal-animate-slide-up');\n document.removeEventListener('click', outsideClick, true);\n document.removeEventListener('keydown', escapeKey, true);\n onClose?.();\n }\n\n function outsideClick(e) {\n // Check if click is inside the shadow host that contains our trigger/panel\n const host = trigger.getRootNode()?.host;\n if (host && !host.contains(e.target) && e.target !== host) {\n close();\n }\n }\n\n function escapeKey(e) {\n if (e.key === 'Escape') {\n e.stopPropagation();\n close();\n }\n }\n\n function destroy() {\n // Teardown without firing onClose (which would mutate store during render)\n if (isOpen) {\n isOpen = false;\n panel.style.display = 'none';\n panel.classList.remove('cal-animate-slide-up');\n }\n document.removeEventListener('click', outsideClick, true);\n document.removeEventListener('keydown', escapeKey, true);\n }\n\n return { panel, open, close, destroy, get isOpen() { return isOpen; } };\n}\n\nexport const popoverStyles = `\n .cal-popover-wrapper {\n position: relative;\n display: inline-block;\n }\n\n .cal-popover {\n position: absolute;\n left: 0;\n z-index: 50;\n background: hsl(var(--cal-bg));\n border: 1px solid hsl(var(--cal-border));\n border-radius: var(--cal-radius);\n box-shadow: 0 4px 16px -2px rgba(0, 0, 0, 0.08), 0 2px 6px -2px rgba(0, 0, 0, 0.04);\n padding: 12px;\n }\n\n .cal-trigger {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 36px;\n padding: 0 12px;\n font-size: 14px;\n border: 1px solid hsl(var(--cal-border));\n border-radius: var(--cal-radius-sm);\n background: hsl(var(--cal-bg));\n color: hsl(var(--cal-fg));\n cursor: pointer;\n transition: border-color var(--cal-transition);\n white-space: nowrap;\n }\n\n .cal-trigger:hover {\n border-color: hsl(var(--cal-fg-muted));\n }\n\n .cal-trigger--placeholder {\n color: hsl(var(--cal-fg-muted));\n }\n\n .cal-trigger__icon {\n display: flex;\n color: hsl(var(--cal-fg-muted));\n }\n`;\n","/**\n * Booking data layer: cell status resolution, validation, and color palette.\n */\n\n/** Color palette mapping from booking color names to CSS token pairs. */\nexport const BOOKING_COLORS = {\n blue: { bg: 'var(--cal-booking-blue-bg)', fg: 'var(--cal-booking-blue-fg)', hover: 'var(--cal-booking-blue-hover)' },\n green: { bg: 'var(--cal-booking-green-bg)', fg: 'var(--cal-booking-green-fg)', hover: 'var(--cal-booking-green-hover)' },\n red: { bg: 'var(--cal-booking-red-bg)', fg: 'var(--cal-booking-red-fg)', hover: 'var(--cal-booking-red-hover)' },\n orange: { bg: 'var(--cal-booking-orange-bg)', fg: 'var(--cal-booking-orange-fg)', hover: 'var(--cal-booking-orange-hover)' },\n gray: { bg: 'var(--cal-booking-gray-bg)', fg: 'var(--cal-booking-gray-fg)', hover: 'var(--cal-booking-gray-hover)' },\n};\n\nconst DEFAULT_COLOR = 'blue';\n\nfunction getColorTokens(colorName) {\n return BOOKING_COLORS[colorName] || BOOKING_COLORS[DEFAULT_COLOR];\n}\n\n/**\n * Resolve cell status for a single date given bookings, dayData, and labelFormula.\n *\n * Priority: labelFormula > dayData > derived from bookings.\n *\n * @param {string} dateStr - ISO date string\n * @param {Array} bookings - array of { id, start, end, label, color }\n * @param {Object} dayData - map of dateStr → { label, status }\n * @param {Function|null} labelFormula - (dateStr) => { label, status }\n * @returns {{ status, label, checkoutBooking, checkinBooking, halfDay, colorOut, colorIn, colorFull }}\n */\nexport function resolveCellData(dateStr, bookings = [], dayData = {}, labelFormula = null) {\n // Find bookings that touch this date\n const checkoutBooking = bookings.find((b) => b.end === dateStr);\n const checkinBooking = bookings.find((b) => b.start === dateStr);\n const spanningBooking = bookings.find(\n (b) => b.start < dateStr && b.end > dateStr\n );\n\n // Derive base status from bookings\n let status = 'available';\n let label = null;\n let halfDay = false;\n let colorOut = null;\n let colorIn = null;\n let colorFull = null;\n\n if (checkoutBooking && checkinBooking) {\n // Half-day: one booking ends, another begins\n status = 'half-day';\n halfDay = true;\n colorOut = getColorTokens(checkoutBooking.color || DEFAULT_COLOR);\n colorIn = getColorTokens(checkinBooking.color || DEFAULT_COLOR);\n } else if (spanningBooking) {\n status = 'booked';\n colorFull = getColorTokens(spanningBooking.color || DEFAULT_COLOR);\n } else if (checkinBooking && !checkoutBooking) {\n // First day of a booking — only the incoming triangle is filled\n status = 'checkin-only';\n colorIn = getColorTokens(checkinBooking.color || DEFAULT_COLOR);\n } else if (checkoutBooking && !checkinBooking) {\n // Last day of a booking (checkout day — could be selectable as checkout boundary)\n status = 'checkout-only';\n colorOut = getColorTokens(checkoutBooking.color || DEFAULT_COLOR);\n }\n\n // Override with dayData (static)\n const staticData = dayData[dateStr];\n if (staticData) {\n if (staticData.status) status = staticData.status;\n if (staticData.label !== undefined) label = staticData.label;\n }\n\n // Override with labelFormula (highest priority)\n if (labelFormula) {\n const formulaResult = labelFormula(dateStr);\n if (formulaResult) {\n if (formulaResult.status) status = formulaResult.status;\n if (formulaResult.label !== undefined) label = formulaResult.label;\n }\n }\n\n return { status, label, checkoutBooking, checkinBooking, halfDay, colorOut, colorIn, colorFull };\n}\n\n/**\n * Validate if a selection range overlaps any existing booking.\n * Same-day checkout/checkin overlap is allowed.\n *\n * @param {string} start - selection start date\n * @param {string} end - selection end date\n * @param {Array} bookings - existing bookings\n * @returns {boolean} true if selection is valid (no overlap)\n */\nexport function isSelectionValid(start, end, bookings = []) {\n if (!start || !end) return true;\n const selStart = start < end ? start : end;\n const selEnd = start < end ? end : start;\n\n for (const booking of bookings) {\n // Same-day boundary is allowed: selection ending on booking start, or starting on booking end\n if (selStart < booking.end && selEnd > booking.start) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Check if a hover preview range would be invalid.\n */\nexport function isHoverRangeInvalid(rangeStart, hoverDate, bookings = []) {\n if (!rangeStart || !hoverDate) return false;\n return !isSelectionValid(rangeStart, hoverDate, bookings);\n}\n","import { buildMonthGrid, getWeekdayLabels, isSameDay, isInRange } from '../../core/dates.js';\nimport { resolveCellData, isHoverRangeInvalid } from '../booking/booking-data.js';\n\n/**\n * Renders a 7×6 month grid.\n * Supports both datepicker mode (default) and booking mode (when bookings param is provided).\n *\n * @param {object} options\n * @param {number} options.year\n * @param {number} options.month\n * @param {number} options.firstDay - 0=Sun, 1=Mon\n * @param {string[]} options.selectedDates - ISO date strings\n * @param {string|null} options.rangeStart\n * @param {string|null} options.rangeEnd\n * @param {string|null} options.hoverDate - for range preview\n * @param {string|null} options.minDate\n * @param {string|null} options.maxDate\n * @param {string[]} options.disabledDates\n * @param {string} options.mode - single|range|multi\n * @param {string|null} options.focusedDate - date that should receive tabindex=0\n * @param {function} options.onSelect\n * @param {function} options.onHover\n * @param {Array|null} options.bookings - booking data (enables booking mode)\n * @param {Object|null} options.dayData - map of dateStr → { label, status }\n * @param {Function|null} options.labelFormula - (dateStr) => { label, status }\n * @param {boolean} options.showLabelsOnHover - show booking labels as tooltips\n * @returns {HTMLElement}\n */\nexport function renderCalendarGrid(options) {\n const {\n year, month, firstDay = 0,\n selectedDates = [], rangeStart, rangeEnd, hoverDate,\n minDate, maxDate, disabledDates = [],\n mode = 'single', focusedDate,\n onSelect, onHover,\n // Booking-specific params\n bookings = null, dayData = null, labelFormula = null,\n showLabelsOnHover = false,\n } = options;\n\n const isBookingMode = bookings !== null;\n\n const grid = document.createElement('div');\n grid.setAttribute('role', 'grid');\n grid.classList.add('cal-grid');\n\n // Weekday header row\n const headerRow = document.createElement('div');\n headerRow.setAttribute('role', 'row');\n headerRow.classList.add('cal-weekdays');\n for (const label of getWeekdayLabels(firstDay)) {\n const cell = document.createElement('div');\n cell.setAttribute('role', 'columnheader');\n cell.setAttribute('aria-label', label);\n cell.classList.add('cal-weekday');\n cell.textContent = label;\n headerRow.appendChild(cell);\n }\n grid.appendChild(headerRow);\n\n // Day cells\n const cells = buildMonthGrid(year, month, firstDay);\n const effectiveEnd = mode === 'range' && rangeStart && !rangeEnd && hoverDate\n ? hoverDate\n : (isBookingMode && rangeStart && !rangeEnd && hoverDate ? hoverDate : rangeEnd);\n\n // Booking: detect invalid hover range\n const hoverInvalid = isBookingMode\n ? isHoverRangeInvalid(rangeStart, hoverDate, bookings)\n : false;\n\n let row;\n cells.forEach((cell, i) => {\n if (i % 7 === 0) {\n row = document.createElement('div');\n row.setAttribute('role', 'row');\n row.classList.add('cal-row');\n grid.appendChild(row);\n }\n\n const btn = document.createElement('button');\n btn.setAttribute('role', 'gridcell');\n btn.setAttribute('part', 'day');\n btn.classList.add('cal-day');\n\n const dateStr = cell.dateString;\n btn.dataset.date = dateStr;\n\n // Accessibility label\n const dateObj = new Date(cell.year, cell.month, cell.day);\n btn.setAttribute('aria-label', dateObj.toLocaleDateString('en-US', {\n weekday: 'long', year: 'numeric', month: 'long', day: 'numeric',\n }));\n\n // Outside month\n if (!cell.isCurrentMonth) {\n btn.classList.add('cal-day--outside');\n }\n\n // Today\n if (cell.isToday) {\n btn.classList.add('cal-day--today');\n }\n\n // --- Booking mode: resolve cell data and apply booking classes ---\n let cellData = null;\n let bookingDisabled = false;\n\n if (isBookingMode) {\n cellData = resolveCellData(dateStr, bookings, dayData || {}, labelFormula);\n const { status, label, halfDay, colorOut, colorIn, colorFull } = cellData;\n\n if (status === 'booked') {\n btn.classList.add('cal-day--booked');\n if (colorFull) {\n btn.style.setProperty('--booking-bg', `hsl(${colorFull.bg})`);\n btn.style.setProperty('--booking-fg', `hsl(${colorFull.fg})`);\n btn.style.setProperty('--booking-hover', `hsl(${colorFull.hover})`);\n }\n bookingDisabled = true;\n }\n\n if (status === 'blocked') {\n btn.classList.add('cal-day--blocked');\n bookingDisabled = true;\n }\n\n if (halfDay) {\n btn.classList.add('cal-day--half-day');\n if (colorOut) btn.style.setProperty('--half-day-color-out', `hsl(${colorOut.bg})`);\n if (colorIn) btn.style.setProperty('--half-day-color-in', `hsl(${colorIn.bg})`);\n bookingDisabled = true;\n }\n\n if (status === 'checkout-only') {\n btn.classList.add('cal-day--checkout-only');\n if (colorOut) {\n btn.style.setProperty('--half-day-color-out', `hsl(${colorOut.bg})`);\n }\n }\n\n if (status === 'checkin-only') {\n btn.classList.add('cal-day--checkin-only');\n if (colorIn) {\n btn.style.setProperty('--half-day-color-in', `hsl(${colorIn.bg})`);\n }\n }\n\n // Tooltip: show booking label on hover\n if (showLabelsOnHover) {\n let tooltipLabel = null;\n if (halfDay && cellData.checkoutBooking && cellData.checkinBooking) {\n tooltipLabel = `${cellData.checkoutBooking.label || ''} / ${cellData.checkinBooking.label || ''}`;\n } else if (status === 'booked') {\n const spanning = bookings.find((b) => b.start <= dateStr && b.end > dateStr);\n if (spanning) tooltipLabel = spanning.label;\n } else if (status === 'checkout-only' && cellData.checkoutBooking) {\n tooltipLabel = cellData.checkoutBooking.label;\n } else if (status === 'checkin-only' && cellData.checkinBooking) {\n tooltipLabel = cellData.checkinBooking.label;\n }\n if (tooltipLabel) {\n btn.setAttribute('data-booking-label', tooltipLabel);\n }\n }\n\n // Invalid range preview\n if (hoverInvalid && rangeStart && !rangeEnd && hoverDate) {\n const lo = rangeStart < hoverDate ? rangeStart : hoverDate;\n const hi = rangeStart < hoverDate ? hoverDate : rangeStart;\n if (dateStr >= lo && dateStr <= hi) {\n btn.classList.add('cal-day--invalid-range');\n }\n }\n }\n\n // --- Selected ---\n if (isBookingMode) {\n // In booking mode, selected means rangeStart or rangeEnd\n const isSelected = rangeStart && rangeEnd\n && (isSameDay(dateStr, rangeStart) || isSameDay(dateStr, rangeEnd));\n if (isSelected) {\n btn.classList.add('cal-day--selected');\n btn.setAttribute('aria-selected', 'true');\n } else {\n btn.setAttribute('aria-selected', 'false');\n }\n } else {\n const isSelected = selectedDates.some((d) => isSameDay(d, dateStr));\n if (isSelected) {\n btn.classList.add('cal-day--selected');\n btn.setAttribute('aria-selected', 'true');\n } else {\n btn.setAttribute('aria-selected', 'false');\n }\n }\n\n // Range highlighting\n if ((mode === 'range' || isBookingMode) && rangeStart && effectiveEnd) {\n const isStart = isSameDay(dateStr, rangeStart);\n const isEnd = isSameDay(dateStr, effectiveEnd);\n const inRange = isInRange(dateStr, rangeStart, effectiveEnd);\n\n if (isStart) btn.classList.add('cal-day--range-start');\n if (isEnd) btn.classList.add('cal-day--range-end');\n if (inRange && !isStart && !isEnd) btn.classList.add('cal-day--in-range');\n }\n\n // Disabled\n const isDisabled = isDateDisabled(dateStr, minDate, maxDate, disabledDates);\n const effectiveDisabled = isDisabled || bookingDisabled;\n if (effectiveDisabled) {\n btn.classList.add('cal-day--disabled');\n btn.disabled = true;\n btn.setAttribute('aria-disabled', 'true');\n }\n\n // Focus management\n if (focusedDate && isSameDay(dateStr, focusedDate)) {\n btn.setAttribute('tabindex', '0');\n } else {\n btn.setAttribute('tabindex', '-1');\n }\n\n // --- Cell content ---\n if (isBookingMode && cellData && cellData.label != null) {\n // Sublabel layout: number + label\n btn.classList.add('cal-day--with-label');\n const numSpan = document.createElement('span');\n numSpan.classList.add('cal-day__number');\n numSpan.textContent = cell.day;\n btn.appendChild(numSpan);\n\n const labelSpan = document.createElement('span');\n labelSpan.classList.add('cal-day__label');\n labelSpan.textContent = cellData.label;\n btn.appendChild(labelSpan);\n } else {\n btn.textContent = cell.day;\n }\n\n // Events\n if (!effectiveDisabled) {\n btn.addEventListener('click', () => onSelect?.(dateStr));\n btn.addEventListener('mouseenter', () => onHover?.(dateStr));\n } else if (isBookingMode) {\n // Even disabled booking cells trigger hover for range preview\n btn.addEventListener('mouseenter', () => onHover?.(dateStr));\n }\n\n row.appendChild(btn);\n });\n\n grid.addEventListener('mouseleave', () => onHover?.(null));\n\n return grid;\n}\n\nfunction isDateDisabled(dateStr, minDate, maxDate, disabledDates) {\n if (disabledDates.includes(dateStr)) return true;\n if (minDate && dateStr < minDate) return true;\n if (maxDate && dateStr > maxDate) return true;\n return false;\n}\n\nexport const calendarGridStyles = `\n .cal-grid {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .cal-weekdays {\n display: grid;\n grid-template-columns: repeat(7, var(--cal-cell-size));\n gap: 0;\n margin-bottom: 4px;\n }\n\n .cal-weekday {\n display: flex;\n align-items: center;\n justify-content: center;\n height: var(--cal-cell-size);\n font-size: 12px;\n font-weight: 500;\n color: hsl(var(--cal-fg-muted));\n user-select: none;\n }\n\n .cal-row {\n display: grid;\n grid-template-columns: repeat(7, var(--cal-cell-size));\n gap: 0;\n }\n\n .cal-day {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--cal-cell-size);\n height: var(--cal-cell-size);\n font-size: 14px;\n border-radius: var(--cal-radius-sm);\n transition: background var(--cal-transition), color var(--cal-transition);\n position: relative;\n user-select: none;\n }\n\n .cal-day:not(.cal-day--disabled):not(.cal-day--selected):not(.cal-day--booked):not(.cal-day--half-day):not(.cal-day--blocked):not(.cal-day--checkout-only):not(.cal-day--checkin-only):hover {\n background: hsl(var(--cal-hover));\n }\n\n .cal-day--outside {\n color: hsl(var(--cal-fg-muted));\n opacity: 0.4;\n }\n\n .cal-day--today:not(.cal-day--selected):not(.cal-day--booked):not(.cal-day--half-day):not(.cal-day--checkout-only):not(.cal-day--checkin-only) {\n border: 1px solid hsl(var(--cal-border));\n font-weight: 600;\n }\n\n .cal-day--selected {\n background: hsl(var(--cal-accent));\n color: hsl(var(--cal-accent-fg));\n font-weight: 600;\n }\n\n .cal-day--range-start {\n background: hsl(var(--cal-accent));\n color: hsl(var(--cal-accent-fg));\n font-weight: 600;\n border-radius: var(--cal-radius-sm) 0 0 var(--cal-radius-sm);\n }\n\n .cal-day--range-end {\n background: hsl(var(--cal-accent));\n color: hsl(var(--cal-accent-fg));\n font-weight: 600;\n border-radius: 0 var(--cal-radius-sm) var(--cal-radius-sm) 0;\n }\n\n .cal-day--range-start.cal-day--range-end {\n border-radius: var(--cal-radius-sm);\n }\n\n .cal-day--in-range {\n background: hsl(var(--cal-accent-subtle));\n border-radius: 0;\n }\n\n .cal-day--in-range:hover {\n background: hsl(var(--cal-accent-subtle)) !important;\n }\n\n .cal-day--disabled {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n /* ── Booking-specific styles ── */\n\n /* Booked (fully occupied) */\n .cal-day--booked {\n background: var(--booking-bg, hsl(var(--cal-booking-blue-bg)));\n color: var(--booking-fg, hsl(var(--cal-booking-blue-fg)));\n cursor: not-allowed;\n }\n\n .cal-day--booked:hover {\n background: var(--booking-hover, hsl(var(--cal-booking-blue-hover)));\n }\n\n /* Blocked */\n .cal-day--blocked {\n background: hsl(var(--cal-bg-muted));\n opacity: 0.4;\n cursor: not-allowed;\n }\n\n /* Half-day diagonal (checkout + checkin on same day) */\n .cal-day--half-day {\n background: linear-gradient(135deg,\n var(--half-day-color-out, hsl(var(--cal-booking-blue-bg))) 49.5%,\n hsl(var(--cal-bg)) 49.5%, hsl(var(--cal-bg)) 50.5%,\n var(--half-day-color-in, hsl(var(--cal-booking-green-bg))) 50.5%);\n cursor: not-allowed;\n }\n\n /* Checkout-only (last day of a booking — outgoing triangle) */\n .cal-day--checkout-only {\n background: linear-gradient(135deg,\n var(--half-day-color-out, hsl(var(--cal-booking-blue-bg))) 49.5%,\n hsl(var(--cal-bg)) 49.5%);\n }\n\n /* Checkin-only (first day of a booking — incoming triangle) */\n .cal-day--checkin-only {\n background: linear-gradient(135deg,\n hsl(var(--cal-bg)) 50.5%,\n var(--half-day-color-in, hsl(var(--cal-booking-blue-bg))) 50.5%);\n }\n\n /* Diagonal cells: standard text color for clean contrast */\n .cal-day--half-day,\n .cal-day--checkout-only,\n .cal-day--checkin-only {\n color: hsl(var(--cal-fg));\n }\n\n /* ── Diagonal + selection compounds ── */\n\n /* Checkout-only — range boundary: accent-subtle fill + refined ring */\n .cal-day--checkout-only.cal-day--range-start,\n .cal-day--checkout-only.cal-day--range-end,\n .cal-day--checkout-only.cal-day--selected {\n background: linear-gradient(135deg,\n var(--half-day-color-out, hsl(var(--cal-booking-blue-bg))) 49.5%,\n hsl(var(--cal-accent-subtle)) 50.5%);\n color: hsl(var(--cal-fg));\n box-shadow: inset 0 0 0 1.5px hsl(var(--cal-accent) / 0.3);\n }\n\n /* Checkout-only — in range: accent-subtle fill */\n .cal-day--checkout-only.cal-day--in-range {\n background: linear-gradient(135deg,\n var(--half-day-color-out, hsl(var(--cal-booking-blue-bg))) 49.5%,\n hsl(var(--cal-accent-subtle)) 50.5%);\n }\n\n /* Checkin-only — range boundary: accent-subtle fill + refined ring */\n .cal-day--checkin-only.cal-day--range-start,\n .cal-day--checkin-only.cal-day--range-end,\n .cal-day--checkin-only.cal-day--selected {\n background: linear-gradient(135deg,\n hsl(var(--cal-accent-subtle)) 49.5%,\n var(--half-day-color-in, hsl(var(--cal-booking-blue-bg))) 50.5%);\n color: hsl(var(--cal-fg));\n box-shadow: inset 0 0 0 1.5px hsl(var(--cal-accent) / 0.3);\n }\n\n /* Checkin-only — in range: accent-subtle fill */\n .cal-day--checkin-only.cal-day--in-range {\n background: linear-gradient(135deg,\n hsl(var(--cal-accent-subtle)) 49.5%,\n var(--half-day-color-in, hsl(var(--cal-booking-blue-bg))) 50.5%);\n }\n\n /* Half-day in range — accent-subtle stripe between booking triangles */\n .cal-day--half-day.cal-day--in-range {\n background: linear-gradient(135deg,\n var(--half-day-color-out, hsl(var(--cal-booking-blue-bg))) 49.5%,\n hsl(var(--cal-accent-subtle)) 49.5%, hsl(var(--cal-accent-subtle)) 50.5%,\n var(--half-day-color-in, hsl(var(--cal-booking-green-bg))) 50.5%);\n }\n\n /* Invalid range preview (crosses a booking) */\n .cal-day--invalid-range {\n background: hsl(var(--cal-booking-red-bg));\n border-radius: 0;\n }\n\n /* Booked/half-day/diagonal cells stay opaque even when disabled */\n .cal-day--disabled.cal-day--booked,\n .cal-day--disabled.cal-day--half-day,\n .cal-day--disabled.cal-day--checkout-only,\n .cal-day--disabled.cal-day--checkin-only {\n opacity: 1;\n }\n\n /* Sublabel spans */\n .cal-day__number {\n font-size: 13px;\n font-weight: 500;\n line-height: 1;\n }\n\n .cal-day__label {\n font-size: 9px;\n font-weight: 500;\n line-height: 1;\n opacity: 0.8;\n }\n\n .cal-day--with-label {\n flex-direction: column;\n gap: 1px;\n }\n\n /* CSS Tooltip */\n .cal-day[data-booking-label] {\n overflow: visible;\n }\n\n .cal-day[data-booking-label]:hover::after {\n content: attr(data-booking-label);\n position: absolute;\n bottom: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%);\n padding: 4px 8px;\n font-size: 11px;\n font-weight: 500;\n white-space: nowrap;\n color: hsl(var(--cal-accent-fg));\n background: hsl(var(--cal-accent));\n border-radius: 4px;\n pointer-events: none;\n z-index: 10;\n }\n\n .cal-day[data-booking-label]:hover::before {\n content: '';\n position: absolute;\n bottom: calc(100% + 2px);\n left: 50%;\n transform: translateX(-50%);\n border: 4px solid transparent;\n border-top-color: hsl(var(--cal-accent));\n pointer-events: none;\n z-index: 10;\n }\n`;\n","/**\n * Time slot grid renderer — pill-shaped slot buttons in a responsive grid.\n */\nimport { formatTime, parseTime, isTimeInRange } from '../../core/times.js';\n\n/**\n * @param {object} options\n * @param {Array<{time: string, label?: string, available?: boolean}>} options.slots\n * @param {string} options.mode - single|multi|range\n * @param {string|null} options.format - '12h'|'24h'\n * @param {string|string[]|{start,end}|null} options.selected\n * @param {string|null} options.hoverTime - for range preview\n * @param {string|null} options.rangeStart - for range mode in-progress\n * @param {string[]} options.unavailableTimes\n * @param {function} options.onSelect\n * @param {function} options.onHover\n * @returns {HTMLElement}\n */\nexport function renderTimeGrid(options) {\n const {\n slots = [], mode = 'single', format = '24h',\n selected, hoverTime, rangeStart,\n unavailableTimes = [],\n onSelect, onHover,\n durationLabels = false,\n } = options;\n\n const grid = document.createElement('div');\n grid.classList.add('cal-time-grid');\n if (durationLabels) grid.classList.add('cal-time-grid--duration');\n grid.setAttribute('role', 'listbox');\n if (mode === 'multi') grid.setAttribute('aria-multiselectable', 'true');\n\n for (const slot of slots) {\n const btn = document.createElement('button');\n btn.classList.add('cal-time-slot');\n btn.setAttribute('role', 'option');\n btn.dataset.time = slot.time;\n\n // Format display text — slot.displayText takes priority\n const parsed = parseTime(slot.time);\n const displayTime = slot.displayText\n ? slot.displayText\n : (parsed ? formatTime(parsed.hours, parsed.minutes, format) : slot.time);\n\n const timeSpan = document.createElement('span');\n timeSpan.classList.add('cal-time-slot__time');\n timeSpan.textContent = displayTime;\n btn.appendChild(timeSpan);\n\n if (slot.label) {\n const labelSpan = document.createElement('span');\n labelSpan.classList.add('cal-time-slot__label');\n labelSpan.textContent = slot.label;\n btn.appendChild(labelSpan);\n }\n\n // Available/unavailable\n const isUnavailable = slot.available === false || unavailableTimes.includes(slot.time);\n if (isUnavailable) {\n btn.classList.add('cal-time-slot--unavailable');\n btn.disabled = true;\n btn.setAttribute('aria-disabled', 'true');\n }\n\n // Selected state\n const isSelected = isSlotSelected(slot.time, selected, mode);\n if (isSelected) {\n btn.classList.add('cal-time-slot--selected');\n btn.setAttribute('aria-selected', 'true');\n } else {\n btn.setAttribute('aria-selected', 'false');\n }\n\n // Range in-progress preview\n if (mode === 'range' && rangeStart && !isRangeComplete(selected) && hoverTime) {\n const inRange = isTimeInRange(slot.time, rangeStart, hoverTime);\n const isStart = slot.time === rangeStart;\n const isEnd = slot.time === hoverTime;\n if (inRange && !isStart && !isEnd) {\n btn.classList.add('cal-time-slot--in-range');\n }\n if (isStart) btn.classList.add('cal-time-slot--range-start');\n if (isEnd) btn.classList.add('cal-time-slot--range-end');\n } else if (mode === 'range' && selected && typeof selected === 'object' && selected.start && selected.end) {\n // Completed range\n const inRange = isTimeInRange(slot.time, selected.start, selected.end);\n const isStart = slot.time === selected.start;\n const isEnd = slot.time === selected.end;\n if (isStart) btn.classList.add('cal-time-slot--range-start', 'cal-time-slot--selected');\n if (isEnd) btn.classList.add('cal-time-slot--range-end', 'cal-time-slot--selected');\n if (inRange && !isStart && !isEnd) btn.classList.add('cal-time-slot--in-range');\n }\n\n // Events\n if (!isUnavailable) {\n btn.addEventListener('click', () => onSelect?.(slot.time));\n btn.addEventListener('mouseenter', () => onHover?.(slot.time));\n }\n\n grid.appendChild(btn);\n }\n\n grid.addEventListener('mouseleave', () => onHover?.(null));\n\n return grid;\n}\n\nfunction isSlotSelected(time, selected, mode) {\n if (!selected) return false;\n if (mode === 'single') return selected === time;\n if (mode === 'multi') return Array.isArray(selected) && selected.includes(time);\n if (mode === 'range') {\n if (typeof selected === 'object' && selected.start && selected.end) {\n return selected.start === time || selected.end === time;\n }\n }\n return false;\n}\n\nfunction isRangeComplete(selected) {\n return selected && typeof selected === 'object' && selected.start && selected.end;\n}\n\nexport const timeGridStyles = `\n .cal-time-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));\n gap: 6px;\n max-height: 280px;\n overflow-y: auto;\n padding: 4px;\n }\n\n .cal-time-grid::-webkit-scrollbar {\n width: 6px;\n }\n\n .cal-time-grid::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .cal-time-grid::-webkit-scrollbar-thumb {\n background: hsl(var(--cal-border));\n border-radius: 3px;\n }\n\n .cal-time-slot {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 40px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 13px;\n background: hsl(var(--cal-bg-muted));\n color: hsl(var(--cal-fg));\n transition: background var(--cal-transition), color var(--cal-transition);\n gap: 1px;\n }\n\n .cal-time-slot:not(.cal-time-slot--unavailable):not(.cal-time-slot--selected):hover {\n background: hsl(var(--cal-hover));\n }\n\n .cal-time-slot__time {\n font-weight: 500;\n line-height: 1;\n }\n\n .cal-time-slot__label {\n font-size: 9px;\n opacity: 0.7;\n line-height: 1;\n }\n\n .cal-time-slot--selected {\n background: hsl(var(--cal-accent));\n color: hsl(var(--cal-accent-fg));\n font-weight: 600;\n }\n\n .cal-time-slot--in-range {\n background: hsl(var(--cal-accent-subtle));\n }\n\n .cal-time-slot--range-start,\n .cal-time-slot--range-end {\n background: hsl(var(--cal-accent));\n color: hsl(var(--cal-accent-fg));\n font-weight: 600;\n }\n\n .cal-time-slot--unavailable {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n .cal-time-grid--duration {\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n }\n\n .cal-time-grid--duration .cal-time-slot {\n font-size: 12px;\n }\n`;\n","/**\n * Loading skeleton renderers for shimmer placeholders.\n */\n\n/**\n * Render a skeleton matching the time grid layout.\n * @param {object} options\n * @param {number} options.columns - grid columns (default 3)\n * @param {number} options.rows - number of rows (default 4)\n * @param {boolean} options.durationLabels - wider pills for duration labels\n * @returns {HTMLElement}\n */\nexport function renderTimeGridSkeleton({ columns = 3, rows = 4, durationLabels = false } = {}) {\n const wrapper = document.createElement('div');\n wrapper.setAttribute('role', 'status');\n wrapper.setAttribute('aria-label', 'Loading...');\n wrapper.classList.add('cal-skeleton-time-grid');\n if (durationLabels) wrapper.classList.add('cal-skeleton-time-grid--duration');\n\n const count = columns * rows;\n for (let i = 0; i < count; i++) {\n const pill = document.createElement('div');\n pill.classList.add('cal-skeleton');\n wrapper.appendChild(pill);\n }\n return wrapper;\n}\n\n/**\n * Render a skeleton matching the calendar day grid layout.\n * @param {object} options\n * @param {number} options.rows - number of week rows (default 5)\n * @returns {HTMLElement}\n */\nexport function renderCalendarGridSkeleton({ rows = 5 } = {}) {\n const wrapper = document.createElement('div');\n wrapper.setAttribute('role', 'status');\n wrapper.setAttribute('aria-label', 'Loading...');\n wrapper.classList.add('cal-skeleton-calendar-grid');\n\n // Header row (7 day labels)\n for (let i = 0; i < 7; i++) {\n const label = document.createElement('div');\n label.classList.add('cal-skeleton', 'cal-skeleton-calendar-grid__header');\n wrapper.appendChild(label);\n }\n\n // Day cells\n const count = 7 * rows;\n for (let i = 0; i < count; i++) {\n const cell = document.createElement('div');\n cell.classList.add('cal-skeleton', 'cal-skeleton-calendar-grid__day');\n wrapper.appendChild(cell);\n }\n return wrapper;\n}\n\nexport const loadingSkeletonStyles = `\n .cal-skeleton-time-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));\n gap: 6px;\n padding: 4px;\n }\n\n .cal-skeleton-time-grid--duration {\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n }\n\n .cal-skeleton-time-grid .cal-skeleton {\n height: 40px;\n }\n\n .cal-skeleton-calendar-grid {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n gap: 2px;\n padding: 4px;\n }\n\n .cal-skeleton-calendar-grid__header {\n height: 20px;\n margin-bottom: 4px;\n }\n\n .cal-skeleton-calendar-grid__day {\n height: var(--cal-cell-size, 36px);\n aspect-ratio: 1;\n border-radius: var(--cal-radius-sm) !important;\n }\n`;\n","/**\n * Status message renderer — inline banners with type-specific icons and colors.\n */\n\nconst icons = {\n error: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><circle cx=\"7\" cy=\"7\" r=\"6\"/><path d=\"M7 4v3M7 9.5v.01\"/></svg>`,\n warning: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><path d=\"M7 1.5L1 12.5h12L7 1.5zM7 6v2.5M7 10.5v.01\"/></svg>`,\n info: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><circle cx=\"7\" cy=\"7\" r=\"6\"/><path d=\"M7 6.5V10M7 4.5v.01\"/></svg>`,\n success: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><circle cx=\"7\" cy=\"7\" r=\"6\"/><path d=\"M4.5 7l2 2L9.5 5\"/></svg>`,\n};\n\n/**\n * Render a status message banner.\n * @param {object} options\n * @param {'error'|'warning'|'info'|'success'} options.type\n * @param {string} options.message\n * @param {boolean} options.dismissible\n * @param {function} options.onDismiss\n * @returns {HTMLElement}\n */\nexport function renderStatusMessage({ type = 'info', message, dismissible = true, onDismiss }) {\n const banner = document.createElement('div');\n banner.classList.add('cal-status', `cal-status--${type}`, 'cal-animate-slide-up');\n banner.setAttribute('role', type === 'error' ? 'alert' : 'status');\n banner.setAttribute('aria-live', type === 'error' ? 'assertive' : 'polite');\n\n const icon = document.createElement('span');\n icon.classList.add('cal-status__icon');\n icon.innerHTML = icons[type] || icons.info;\n banner.appendChild(icon);\n\n const text = document.createElement('span');\n text.classList.add('cal-status__text');\n text.textContent = message;\n banner.appendChild(text);\n\n if (dismissible) {\n const closeBtn = document.createElement('button');\n closeBtn.classList.add('cal-status__close');\n closeBtn.setAttribute('aria-label', 'Dismiss');\n closeBtn.innerHTML = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"><path d=\"M3 3l6 6M9 3l-6 6\"/></svg>`;\n closeBtn.addEventListener('click', () => onDismiss?.());\n banner.appendChild(closeBtn);\n }\n\n return banner;\n}\n\nexport const statusMessageStyles = `\n .cal-status {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: var(--cal-radius-sm);\n font-size: 12px;\n line-height: 1.4;\n margin-bottom: 8px;\n }\n\n .cal-status__icon {\n flex-shrink: 0;\n display: flex;\n }\n\n .cal-status__text {\n flex: 1;\n min-width: 0;\n }\n\n .cal-status__close {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 4px;\n cursor: pointer;\n opacity: 0.7;\n transition: opacity var(--cal-transition);\n }\n\n .cal-status__close:hover {\n opacity: 1;\n }\n\n .cal-status--error {\n background: hsl(var(--cal-status-error-bg));\n color: hsl(var(--cal-status-error-fg));\n border: 1px solid hsl(var(--cal-status-error-border));\n }\n\n .cal-status--warning {\n background: hsl(var(--cal-status-warning-bg));\n color: hsl(var(--cal-status-warning-fg));\n border: 1px solid hsl(var(--cal-status-warning-border));\n }\n\n .cal-status--info {\n background: hsl(var(--cal-status-info-bg));\n color: hsl(var(--cal-status-info-fg));\n border: 1px solid hsl(var(--cal-status-info-border));\n }\n\n .cal-status--success {\n background: hsl(var(--cal-status-success-bg));\n color: hsl(var(--cal-status-success-fg));\n border: 1px solid hsl(var(--cal-status-success-border));\n }\n`;\n","import { CalendarBase } from '../../core/base-component.js';\nimport { createStore } from '../../core/state.js';\nimport {\n today, parseDate, toDateString, isSameDay, addMonths, MONTH_NAMES,\n} from '../../core/dates.js';\nimport { generateSlots, generateDurationSlots } from '../../core/times.js';\nimport { tokens } from '../../styles/tokens.js';\nimport { reset } from '../../styles/reset.js';\nimport { animations } from '../../styles/animations.js';\nimport { renderNavigation, navigationStyles } from '../datepicker/navigation.js';\nimport { renderMonthYearPicker, monthYearPickerStyles } from '../datepicker/month-year-picker.js';\nimport { createPopover, popoverStyles } from '../datepicker/popover.js';\nimport { renderCalendarGrid, calendarGridStyles } from '../datepicker/calendar-grid.js';\nimport { renderTimeGrid, timeGridStyles } from '../timepicker/time-grid.js';\nimport { isSelectionValid } from './booking-data.js';\nimport { renderTimeGridSkeleton, renderCalendarGridSkeleton, loadingSkeletonStyles } from '../shared/loading-skeleton.js';\nimport { renderStatusMessage, statusMessageStyles } from '../shared/status-message.js';\n\nconst calendarIcon = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"2\" y=\"3\" width=\"12\" height=\"11\" rx=\"2\"/><path d=\"M5 1v3M11 1v3M2 7h12\"/></svg>`;\n\nconst componentStyles = `\n .cal-picker {\n background: hsl(var(--cal-bg));\n border-radius: var(--cal-radius);\n user-select: none;\n }\n\n :host([display=\"inline\"]) .cal-picker {\n border: 1px solid hsl(var(--cal-border));\n padding: 12px;\n }\n\n .cal-months {\n display: flex;\n gap: 16px;\n }\n\n .cal-month {\n flex: 0 0 auto;\n }\n\n /* Time section */\n .cal-booking-time-section {\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid hsl(var(--cal-border));\n }\n\n .cal-booking-time-header {\n font-size: 13px;\n font-weight: 600;\n color: hsl(var(--cal-fg));\n margin-bottom: 8px;\n }\n`;\n\nexport class CalBooking extends CalendarBase {\n static get styles() {\n return [tokens, reset, animations, calendarGridStyles, timeGridStyles, navigationStyles, monthYearPickerStyles, popoverStyles, loadingSkeletonStyles, statusMessageStyles, componentStyles];\n }\n\n static get observedAttributes() {\n return [\n 'theme', 'display', 'min-date', 'max-date', 'first-day',\n 'placeholder', 'dual', 'show-labels-on-hover',\n 'time-slots', 'time-start', 'time-end', 'time-interval', 'time-format',\n 'duration-labels', 'loading',\n ];\n }\n\n constructor() {\n super();\n\n const now = new Date();\n this._store = createStore({\n viewYear: now.getFullYear(),\n viewMonth: now.getMonth(),\n rangeStart: null,\n rangeEnd: null,\n hoverDate: null,\n isOpen: false,\n focusedDate: today(),\n navDirection: null,\n pickingMonth: false,\n pickerYear: now.getFullYear(),\n // Time state\n startTime: null,\n endTime: null,\n timeSelectPhase: null, // null | 'start' | 'end'\n // Status\n statusType: null,\n statusMessage: null,\n statusDismissible: true,\n });\n\n this._bookings = [];\n this._dayData = {};\n this._labelFormula = null;\n this._timeSlots = null; // explicit slot definitions\n this._popover = null;\n this._unsubscribe = null;\n this._rendering = false;\n }\n\n // -- Attribute getters --\n get display() { return this.getAttribute('display') || 'inline'; }\n get placeholder() { return this.getAttribute('placeholder') || 'Select dates'; }\n get firstDay() { return parseInt(this.getAttribute('first-day') || '0', 10); }\n get minDate() { return this.getAttribute('min-date') || null; }\n get maxDate() { return this.getAttribute('max-date') || null; }\n get showLabelsOnHover() { return this.hasAttribute('show-labels-on-hover'); }\n get timeSlotsEnabled() { return this.hasAttribute('time-slots'); }\n get timeStartTime() { return this.getAttribute('time-start') || '09:00'; }\n get timeEndTime() { return this.getAttribute('time-end') || '17:00'; }\n get timeInterval() { return parseInt(this.getAttribute('time-interval') || '60', 10); }\n get timeFormat() { return this.getAttribute('time-format') || '24h'; }\n get durationLabels() { return this.hasAttribute('duration-labels'); }\n get loading() { return this.hasAttribute('loading'); }\n set loading(val) { val ? this.setAttribute('loading', '') : this.removeAttribute('loading'); }\n\n // -- Properties --\n get bookings() { return this._bookings; }\n set bookings(val) {\n this._bookings = Array.isArray(val) ? val : [];\n if (this._initialized) this.render();\n }\n\n get dayData() { return this._dayData; }\n set dayData(val) {\n this._dayData = val && typeof val === 'object' ? val : {};\n if (this._initialized) this.render();\n }\n\n get labelFormula() { return this._labelFormula; }\n set labelFormula(fn) {\n this._labelFormula = typeof fn === 'function' ? fn : null;\n if (this._initialized) this.render();\n }\n\n get timeSlots() { return this._timeSlots; }\n set timeSlots(val) {\n this._timeSlots = Array.isArray(val) ? val : null;\n if (this._initialized) this.render();\n }\n\n get value() {\n const state = this._store.getState();\n if (!state.rangeStart || !state.rangeEnd) return null;\n const val = { start: state.rangeStart, end: state.rangeEnd };\n if (this.timeSlotsEnabled) {\n if (state.startTime) val.startTime = state.startTime;\n if (state.endTime) val.endTime = state.endTime;\n }\n return val;\n }\n\n set value(val) {\n if (val && typeof val === 'object' && val.start && val.end) {\n const start = typeof val.start === 'string' ? val.start : toDateString(val.start);\n const end = typeof val.end === 'string' ? val.end : toDateString(val.end);\n const updates = { rangeStart: start, rangeEnd: end };\n if (val.startTime) updates.startTime = val.startTime;\n if (val.endTime) updates.endTime = val.endTime;\n this._store.set(updates);\n this._navigateToDate(start);\n } else {\n this._store.set({\n rangeStart: null, rangeEnd: null,\n startTime: null, endTime: null, timeSelectPhase: null,\n });\n }\n }\n\n _navigateToDate(dateStr) {\n const d = parseDate(dateStr);\n if (d) {\n this._store.set({ viewYear: d.getFullYear(), viewMonth: d.getMonth() });\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n this._unsubscribe = this._store.subscribe((state, prev) => {\n if (this._rendering) return;\n // Hover-only change → lightweight CSS update\n const hoverOnly = state.hoverDate !== prev.hoverDate\n && state.viewYear === prev.viewYear && state.viewMonth === prev.viewMonth\n && state.rangeStart === prev.rangeStart && state.rangeEnd === prev.rangeEnd\n && state.isOpen === prev.isOpen && state.navDirection === prev.navDirection\n && state.pickingMonth === prev.pickingMonth && state.pickerYear === prev.pickerYear\n && state.timeSelectPhase === prev.timeSelectPhase;\n hoverOnly ? this._updateGridHighlight(state) : this.render();\n });\n\n // Parse bookings from attribute (JSON fallback)\n const bookingsAttr = this.getAttribute('bookings');\n if (bookingsAttr && !this._bookings.length) {\n try { this._bookings = JSON.parse(bookingsAttr); } catch (e) { /* ignore */ }\n }\n }\n\n disconnectedCallback() {\n this._unsubscribe?.();\n this._popover?.destroy();\n clearTimeout(this._statusTimer);\n }\n\n attributeChangedCallback(name, oldVal, newVal) {\n if (oldVal === newVal) return;\n if (this._initialized) this.render();\n }\n\n // -- Selection --\n _handleSelect(dateStr) {\n const state = this._store.getState();\n\n if (!state.rangeStart || state.rangeEnd) {\n // Start new range — reset time state\n this._store.set({\n rangeStart: dateStr,\n rangeEnd: null,\n hoverDate: null,\n focusedDate: dateStr,\n startTime: null,\n endTime: null,\n timeSelectPhase: null,\n });\n } else {\n // Complete range\n let start = state.rangeStart;\n let end = dateStr;\n if (start > end) [start, end] = [end, start];\n\n // Validate against bookings\n if (!isSelectionValid(start, end, this._bookings)) {\n this.emit('cal:selection-invalid', { start, end });\n this._store.set({\n rangeStart: null, rangeEnd: null, hoverDate: null,\n startTime: null, endTime: null, timeSelectPhase: null,\n });\n this.showStatus('error', 'Selection overlaps an existing booking', { autoDismiss: 4000 });\n return;\n }\n\n if (this.timeSlotsEnabled) {\n // Don't emit change yet — enter time selection phase\n this._store.set({\n rangeStart: start,\n rangeEnd: end,\n hoverDate: null,\n focusedDate: end,\n timeSelectPhase: 'start',\n });\n } else {\n this._store.set({\n rangeStart: start,\n rangeEnd: end,\n hoverDate: null,\n focusedDate: end,\n });\n this.emit('cal:change', { value: { start, end } });\n if (this.display === 'popover') this.close();\n }\n }\n }\n\n _handleTimeSelect(time) {\n const state = this._store.getState();\n\n if (state.timeSelectPhase === 'start') {\n this._store.set({ startTime: time, timeSelectPhase: 'end' });\n } else if (state.timeSelectPhase === 'end') {\n this._store.set({ endTime: time, timeSelectPhase: null });\n // Emit full value with times\n const value = {\n start: state.rangeStart,\n end: state.rangeEnd,\n startTime: state.startTime,\n endTime: time,\n };\n this.emit('cal:change', { value });\n if (this.display === 'popover') this.close();\n }\n }\n\n _handleHover(dateStr) {\n this._store.set({ hoverDate: dateStr });\n }\n\n // -- Lightweight hover highlight --\n _updateGridHighlight(state) {\n const buttons = this.$$('.cal-day');\n const { rangeStart, hoverDate } = state;\n const effectiveEnd = rangeStart && !state.rangeEnd && hoverDate ? hoverDate : state.rangeEnd;\n\n // Inline check for invalid hover\n let hoverRangeInvalid = false;\n if (rangeStart && !state.rangeEnd && hoverDate) {\n const lo = rangeStart < hoverDate ? rangeStart : hoverDate;\n const hi = rangeStart < hoverDate ? hoverDate : rangeStart;\n for (const b of this._bookings) {\n if (lo < b.end && hi > b.start) { hoverRangeInvalid = true; break; }\n }\n }\n\n for (const btn of buttons) {\n const dateStr = btn.dataset.date;\n if (!dateStr) continue;\n\n const isStart = dateStr === rangeStart && !!effectiveEnd;\n const isEnd = dateStr === effectiveEnd && !!effectiveEnd;\n\n let inRange = false;\n if (rangeStart && effectiveEnd) {\n const lo = rangeStart < effectiveEnd ? rangeStart : effectiveEnd;\n const hi = rangeStart < effectiveEnd ? effectiveEnd : rangeStart;\n inRange = dateStr >= lo && dateStr <= hi && !isStart && !isEnd;\n }\n\n const invalidRange = hoverRangeInvalid && rangeStart && !state.rangeEnd && hoverDate\n && (() => {\n const lo = rangeStart < hoverDate ? rangeStart : hoverDate;\n const hi = rangeStart < hoverDate ? hoverDate : rangeStart;\n return dateStr >= lo && dateStr <= hi;\n })();\n\n btn.classList.toggle('cal-day--range-start', isStart);\n btn.classList.toggle('cal-day--range-end', isEnd);\n btn.classList.toggle('cal-day--in-range', inRange);\n btn.classList.toggle('cal-day--invalid-range', !!invalidRange);\n }\n }\n\n // -- Navigation --\n _prevMonth() {\n const { viewYear, viewMonth } = this._store.getState();\n const { year, month } = addMonths(viewYear, viewMonth, -1);\n this._store.set({ viewYear: year, viewMonth: month, navDirection: 'prev' });\n this.emit('cal:month-change', { year, month });\n }\n\n _nextMonth() {\n const { viewYear, viewMonth } = this._store.getState();\n const { year, month } = addMonths(viewYear, viewMonth, 1);\n this._store.set({ viewYear: year, viewMonth: month, navDirection: 'next' });\n this.emit('cal:month-change', { year, month });\n }\n\n // -- Month picker --\n _toggleMonthPicker() {\n const state = this._store.getState();\n this._store.set({\n pickingMonth: !state.pickingMonth,\n pickerYear: state.viewYear,\n });\n }\n\n _selectMonthFromPicker(month, year) {\n this._store.set({\n viewYear: year,\n viewMonth: month,\n pickingMonth: false,\n });\n this.emit('cal:month-change', { year, month });\n }\n\n // -- Keyboard --\n _handleKeydown(e) {\n if (e.key === 'Escape' && this._store.get('pickingMonth')) {\n e.stopPropagation();\n this._store.set({ pickingMonth: false });\n return;\n }\n\n const state = this._store.getState();\n const focused = parseDate(state.focusedDate);\n if (!focused) return;\n\n let newDate = null;\n switch (e.key) {\n case 'ArrowLeft':\n newDate = new Date(focused); newDate.setDate(focused.getDate() - 1); break;\n case 'ArrowRight':\n newDate = new Date(focused); newDate.setDate(focused.getDate() + 1); break;\n case 'ArrowUp':\n newDate = new Date(focused); newDate.setDate(focused.getDate() - 7); break;\n case 'ArrowDown':\n newDate = new Date(focused); newDate.setDate(focused.getDate() + 7); break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n this._handleSelect(state.focusedDate);\n return;\n case 'Escape':\n if (this.display === 'popover') this.close();\n return;\n default: return;\n }\n\n if (newDate) {\n e.preventDefault();\n const dateStr = toDateString(newDate);\n if (newDate.getMonth() !== state.viewMonth || newDate.getFullYear() !== state.viewYear) {\n this._store.set({\n viewYear: newDate.getFullYear(), viewMonth: newDate.getMonth(),\n focusedDate: dateStr, navDirection: newDate > focused ? 'next' : 'prev',\n });\n } else {\n this._store.set({ focusedDate: dateStr });\n }\n requestAnimationFrame(() => {\n const cell = this.$(`[data-date=\"${dateStr}\"]`);\n cell?.focus();\n });\n }\n }\n\n // -- Public API --\n open() {\n if (this._popover) {\n this._popover.open();\n this._store.set({ isOpen: true });\n this.emit('cal:open');\n }\n }\n\n close() {\n if (this._popover) {\n this._popover.close();\n this._store.set({ isOpen: false });\n this.emit('cal:close');\n }\n }\n\n goToMonth(month, year) {\n this._store.set({ viewYear: year, viewMonth: month });\n }\n\n // -- Time slots generation --\n _getTimeSlotArray() {\n if (this._timeSlots) {\n return this._timeSlots;\n }\n // Generate from attributes\n if (this.durationLabels) {\n return generateDurationSlots(this.timeStartTime, this.timeEndTime, this.timeInterval, this.timeFormat)\n .map((slot) => ({ ...slot, available: true }));\n }\n const times = generateSlots(this.timeStartTime, this.timeEndTime, this.timeInterval);\n return times.map((t) => ({ time: t, available: true }));\n }\n\n // -- Render --\n _renderCalendarContent() {\n const state = this._store.getState();\n const container = document.createElement('div');\n container.classList.add('cal-picker');\n\n // Status banner\n if (state.statusType && state.statusMessage) {\n container.appendChild(renderStatusMessage({\n type: state.statusType,\n message: state.statusMessage,\n dismissible: state.statusDismissible,\n onDismiss: () => this.clearStatus(),\n }));\n }\n\n if (this.loading) {\n const monthsWrapper = document.createElement('div');\n monthsWrapper.classList.add('cal-months');\n const monthEl = document.createElement('div');\n monthEl.classList.add('cal-month');\n monthEl.appendChild(renderCalendarGridSkeleton());\n monthsWrapper.appendChild(monthEl);\n container.appendChild(monthsWrapper);\n if (this.timeSlotsEnabled) {\n const timeSection = document.createElement('div');\n timeSection.classList.add('cal-booking-time-section');\n timeSection.appendChild(renderTimeGridSkeleton({ durationLabels: this.durationLabels }));\n container.appendChild(timeSection);\n }\n container.addEventListener('keydown', (e) => this._handleKeydown(e));\n return container;\n }\n\n const monthsWrapper = document.createElement('div');\n monthsWrapper.classList.add('cal-months');\n\n const showDual = this.hasAttribute('dual');\n const monthCount = showDual ? 2 : 1;\n\n for (let i = 0; i < monthCount; i++) {\n const { year, month } = i === 0\n ? { year: state.viewYear, month: state.viewMonth }\n : addMonths(state.viewYear, state.viewMonth, 1);\n\n const monthEl = document.createElement('div');\n monthEl.classList.add('cal-month');\n\n if (i === 0) {\n monthEl.appendChild(renderNavigation({\n year, month,\n onPrev: state.pickingMonth ? () => {} : () => this._prevMonth(),\n onNext: state.pickingMonth ? () => {} : () => { if (!showDual) this._nextMonth(); },\n onTitleClick: () => this._toggleMonthPicker(),\n }));\n }\n\n if (i === 1) {\n monthEl.appendChild(renderNavigation({\n year, month,\n onPrev: () => {},\n onNext: () => this._nextMonth(),\n }));\n }\n\n // Month picker replaces day grid for first panel\n if (state.pickingMonth && i === 0) {\n const picker = renderMonthYearPicker({\n pickerYear: state.pickerYear,\n viewMonth: state.viewMonth,\n viewYear: state.viewYear,\n onMonthSelect: (m, y) => this._selectMonthFromPicker(m, y),\n onYearPrev: () => this._store.set({ pickerYear: state.pickerYear - 1 }),\n onYearNext: () => this._store.set({ pickerYear: state.pickerYear + 1 }),\n onClose: () => this._store.set({ pickingMonth: false }),\n });\n monthEl.appendChild(picker);\n } else {\n const animClass = state.navDirection === 'next'\n ? 'cal-animate-slide-left'\n : state.navDirection === 'prev'\n ? 'cal-animate-slide-right'\n : '';\n\n const grid = renderCalendarGrid({\n year, month,\n firstDay: this.firstDay,\n rangeStart: state.rangeStart,\n rangeEnd: state.rangeEnd,\n hoverDate: state.hoverDate,\n minDate: this.minDate,\n maxDate: this.maxDate,\n focusedDate: state.focusedDate,\n mode: 'range',\n onSelect: (d) => this._handleSelect(d),\n onHover: (d) => this._handleHover(d),\n // Booking-specific params\n bookings: this._bookings,\n dayData: this._dayData,\n labelFormula: this._labelFormula,\n showLabelsOnHover: this.showLabelsOnHover,\n });\n\n if (animClass) grid.classList.add(animClass);\n monthEl.appendChild(grid);\n }\n monthsWrapper.appendChild(monthEl);\n }\n\n container.appendChild(monthsWrapper);\n\n // Time section (date-then-time flow) — hidden when month picker is open\n if (this.timeSlotsEnabled && state.timeSelectPhase && !state.pickingMonth) {\n const timeSection = document.createElement('div');\n timeSection.classList.add('cal-booking-time-section');\n\n const header = document.createElement('div');\n header.classList.add('cal-booking-time-header');\n header.textContent = state.timeSelectPhase === 'start'\n ? 'Select check-in time'\n : 'Select check-out time';\n timeSection.appendChild(header);\n\n const slots = this._getTimeSlotArray();\n const timeGrid = renderTimeGrid({\n slots,\n mode: 'single',\n format: this.timeFormat,\n selected: state.timeSelectPhase === 'end' ? state.startTime : null,\n onSelect: (t) => this._handleTimeSelect(t),\n onHover: () => {},\n durationLabels: this.durationLabels,\n });\n timeSection.appendChild(timeGrid);\n\n container.appendChild(timeSection);\n }\n\n container.addEventListener('keydown', (e) => this._handleKeydown(e));\n\n return container;\n }\n\n _formatTriggerText() {\n const state = this._store.getState();\n if (state.rangeStart && state.rangeEnd) {\n let text = `${this._formatShortDate(state.rangeStart)} – ${this._formatShortDate(state.rangeEnd)}`;\n if (state.startTime && state.endTime) {\n text += ` (${state.startTime} – ${state.endTime})`;\n }\n return text;\n }\n return null;\n }\n\n _formatShortDate(dateStr) {\n const d = parseDate(dateStr);\n if (!d) return dateStr;\n return `${MONTH_NAMES[d.getMonth()].slice(0, 3)} ${d.getDate()}, ${d.getFullYear()}`;\n }\n\n render() {\n if (this._rendering) return;\n this._rendering = true;\n\n const root = this.shadowRoot;\n\n // Clear non-style children\n const children = [...root.childNodes];\n for (const child of children) {\n if (child.nodeName !== 'STYLE' && !(child instanceof CSSStyleSheet)) {\n root.removeChild(child);\n }\n }\n\n this._popover?.destroy();\n this._popover = null;\n\n if (this.display === 'popover') {\n const wrapper = document.createElement('div');\n wrapper.classList.add('cal-popover-wrapper');\n\n const trigger = document.createElement('button');\n trigger.classList.add('cal-trigger');\n\n const icon = document.createElement('span');\n icon.classList.add('cal-trigger__icon');\n icon.innerHTML = calendarIcon;\n trigger.appendChild(icon);\n\n const text = this._formatTriggerText();\n const label = document.createElement('span');\n if (text) {\n label.textContent = text;\n } else {\n label.textContent = this.placeholder;\n label.classList.add('cal-trigger--placeholder');\n }\n trigger.appendChild(label);\n wrapper.appendChild(trigger);\n\n const content = this._renderCalendarContent();\n const popover = createPopover({\n trigger,\n content,\n onClose: () => {\n this._store.set({ isOpen: false });\n this.emit('cal:close');\n },\n });\n\n wrapper.appendChild(popover.panel);\n root.appendChild(wrapper);\n\n trigger.addEventListener('click', (e) => {\n e.stopPropagation();\n if (popover.isOpen) {\n this.close();\n } else {\n this.open();\n }\n });\n\n this._popover = popover;\n if (this._store.get('isOpen')) {\n popover.open();\n }\n } else {\n root.appendChild(this._renderCalendarContent());\n }\n\n this._store.set({ navDirection: null });\n this._rendering = false;\n }\n}\n","import { CalBooking } from '../components/booking/index.js';\n\nif (!customElements.get('cal-booking')) {\n customElements.define('cal-booking', CalBooking);\n}\n\nexport { CalBooking };\n"],"names":["CalendarBase","sheets","s","sheet","el","name","detail","type","message","opts","autoDismiss","dismissible","selector","createStore","initial","state","listeners","key","partial","prev","changed","fn","MONTH_NAMES","SHORT_WEEKDAYS","getWeekdayLabels","firstDay","labels","i","getDaysInMonth","year","month","getFirstDayOfMonth","toDateString","date","d","y","m","day","parseDate","value","isSameDay","a","b","da","db","isInRange","start","end","e","dt","st","et","today","addMonths","delta","buildMonthGrid","daysInMonth","startOffset","cells","todayStr","daysInPrev","dateString","next","parseTime","str","trimmed","ampmMatch","hours","minutes","period","match24","formatTime","format","mm","timeToMinutes","t","minutesToTime","n","generateSlots","startTime","endTime","intervalMinutes","slots","startMin","endMin","generateDurationSlots","time","nextMin","endSlotTime","parsed","parsedEnd","fromText","toText","isTimeInRange","lo","hi","tokens","reset","animations","chevronLeft","chevronRight","renderNavigation","onPrev","onNext","onTitleClick","nav","prevBtn","titleTag","title","nextBtn","navigationStyles","SHORT_MONTHS","renderMonthYearPicker","pickerYear","viewMonth","viewYear","onMonthSelect","onYearPrev","onYearNext","onClose","wrapper","yearNav","yearLabel","grid","now","todayMonth","todayYear","cell","monthYearPickerStyles","createPopover","trigger","content","panel","isOpen","position","triggerRect","panelHeight","spaceBelow","spaceAbove","open","outsideClick","escapeKey","close","host","_a","destroy","popoverStyles","BOOKING_COLORS","DEFAULT_COLOR","getColorTokens","colorName","resolveCellData","dateStr","bookings","dayData","labelFormula","checkoutBooking","checkinBooking","spanningBooking","status","label","halfDay","colorOut","colorIn","colorFull","staticData","formulaResult","isSelectionValid","selStart","selEnd","booking","isHoverRangeInvalid","rangeStart","hoverDate","renderCalendarGrid","options","selectedDates","rangeEnd","minDate","maxDate","disabledDates","mode","focusedDate","onSelect","onHover","showLabelsOnHover","isBookingMode","headerRow","effectiveEnd","hoverInvalid","row","btn","dateObj","cellData","bookingDisabled","tooltipLabel","spanning","isStart","isEnd","inRange","effectiveDisabled","isDateDisabled","numSpan","labelSpan","calendarGridStyles","renderTimeGrid","selected","hoverTime","unavailableTimes","durationLabels","slot","displayTime","timeSpan","isUnavailable","isSlotSelected","isRangeComplete","timeGridStyles","renderTimeGridSkeleton","columns","rows","count","pill","renderCalendarGridSkeleton","loadingSkeletonStyles","icons","renderStatusMessage","onDismiss","banner","icon","text","closeBtn","statusMessageStyles","calendarIcon","componentStyles","CalBooking","val","updates","bookingsAttr","_b","oldVal","newVal","buttons","hoverRangeInvalid","invalidRange","focused","newDate","container","monthsWrapper","monthEl","timeSection","showDual","monthCount","picker","animClass","header","timeGrid","root","children","child","popover"],"mappings":"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"}
|