calkit 0.1.0 → 0.2.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.
@@ -1 +1 @@
1
- {"version":3,"file":"timepicker.es.js","sources":["../src/core/base-component.js","../src/core/state.js","../src/core/times.js","../src/styles/tokens.js","../src/styles/reset.js","../src/styles/animations.js","../src/components/datepicker/popover.js","../src/components/timepicker/time-grid.js","../src/components/shared/loading-skeleton.js","../src/components/shared/status-message.js","../src/components/timepicker/index.js","../src/entries/timepicker.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","/**\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","/**\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 * 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 { generateSlots, generateDurationSlots, timeToMinutes } from '../../core/times.js';\nimport { tokens } from '../../styles/tokens.js';\nimport { reset } from '../../styles/reset.js';\nimport { animations } from '../../styles/animations.js';\nimport { createPopover, popoverStyles } from '../datepicker/popover.js';\nimport { renderTimeGrid, timeGridStyles } from './time-grid.js';\nimport { renderTimeGridSkeleton, loadingSkeletonStyles } from '../shared/loading-skeleton.js';\nimport { renderStatusMessage, statusMessageStyles } from '../shared/status-message.js';\n\nconst clockIcon = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M8 4.5V8l2.5 1.5\"/></svg>`;\n\nconst componentStyles = `\n .cal-timepicker {\n background: hsl(var(--cal-bg));\n border-radius: var(--cal-radius);\n user-select: none;\n min-width: 200px;\n }\n\n :host([display=\"inline\"]) .cal-timepicker {\n border: 1px solid hsl(var(--cal-border));\n padding: 12px;\n }\n\n .cal-timepicker__header {\n font-size: 14px;\n font-weight: 600;\n color: hsl(var(--cal-fg));\n margin-bottom: 8px;\n padding: 0 4px;\n }\n`;\n\nexport class CalTimepicker extends CalendarBase {\n static get styles() {\n return [tokens, reset, animations, timeGridStyles, popoverStyles, loadingSkeletonStyles, statusMessageStyles, componentStyles];\n }\n\n static get observedAttributes() {\n return ['mode', 'display', 'theme', 'start-time', 'end-time', 'interval', 'format', 'placeholder', 'value', 'duration-labels', 'loading'];\n }\n\n constructor() {\n super();\n\n this._store = createStore({\n selected: null, // string | string[] | {start, end}\n rangeStart: null, // for range mode in-progress\n hoverTime: null,\n isOpen: false,\n statusType: null,\n statusMessage: null,\n statusDismissible: true,\n });\n\n this._slots = null; // explicit slots (highest priority)\n this._unavailableTimes = [];\n this._popover = null;\n this._unsubscribe = null;\n this._rendering = false;\n }\n\n // -- Attribute getters --\n get mode() { return this.getAttribute('mode') || 'single'; }\n get display() { return this.getAttribute('display') || 'inline'; }\n get placeholder() { return this.getAttribute('placeholder') || 'Select time'; }\n get startTime() { return this.getAttribute('start-time') || '09:00'; }\n get endTime() { return this.getAttribute('end-time') || '17:00'; }\n get interval() { return parseInt(this.getAttribute('interval') || '30', 10); }\n get format() { return this.getAttribute('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 slots() { return this._slots; }\n set slots(val) {\n this._slots = Array.isArray(val) ? val : null;\n if (this._initialized) this.render();\n }\n\n get unavailableTimes() { return this._unavailableTimes; }\n set unavailableTimes(val) {\n this._unavailableTimes = Array.isArray(val) ? val : [];\n if (this._initialized) this.render();\n }\n\n get value() {\n const state = this._store.getState();\n return state.selected;\n }\n\n set value(val) {\n if (this.mode === 'single' && typeof val === 'string') {\n this._store.set({ selected: val, rangeStart: null });\n } else if (this.mode === 'multi' && Array.isArray(val)) {\n this._store.set({ selected: [...val].sort((a, b) => timeToMinutes(a) - timeToMinutes(b)), rangeStart: null });\n } else if (this.mode === 'range' && val && typeof val === 'object') {\n this._store.set({ selected: { start: val.start, end: val.end }, rangeStart: null });\n } else {\n this._store.set({ selected: null, rangeStart: null });\n }\n }\n\n _getEffectiveSlots() {\n // Priority 1: explicit slots property\n if (this._slots) return this._slots;\n // Priority 2: auto-generate from attributes\n if (this.durationLabels) {\n const durationSlots = generateDurationSlots(this.startTime, this.endTime, this.interval, this.format);\n return durationSlots.map((slot) => ({\n ...slot,\n available: !this._unavailableTimes.includes(slot.time),\n }));\n }\n const times = generateSlots(this.startTime, this.endTime, this.interval);\n return times.map((time) => ({\n time,\n available: !this._unavailableTimes.includes(time),\n }));\n }\n\n connectedCallback() {\n super.connectedCallback();\n this._unsubscribe = this._store.subscribe((state, prev) => {\n if (this._rendering) return;\n // Hover-only → lightweight update\n const hoverOnly = state.hoverTime !== prev.hoverTime\n && state.selected === prev.selected\n && state.rangeStart === prev.rangeStart\n && state.isOpen === prev.isOpen;\n hoverOnly ? this._updateSlotHighlight(state) : this.render();\n });\n\n // Parse initial value attribute\n const valueAttr = this.getAttribute('value');\n if (valueAttr) {\n if (this.mode === 'multi' && valueAttr.includes(',')) {\n this.value = valueAttr.split(',').map((t) => t.trim());\n } else if (this.mode === 'range' && valueAttr.includes('/')) {\n const [start, end] = valueAttr.split('/');\n this.value = { start: start.trim(), end: end.trim() };\n } else {\n this.value = valueAttr;\n }\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 (name === 'value' && this._initialized) {\n if (this.mode === 'multi' && newVal && newVal.includes(',')) {\n this.value = newVal.split(',').map((t) => t.trim());\n } else if (this.mode === 'range' && newVal && newVal.includes('/')) {\n const [start, end] = newVal.split('/');\n this.value = { start: start.trim(), end: end.trim() };\n } else {\n this.value = newVal;\n }\n }\n if (this._initialized) this.render();\n }\n\n // -- Selection --\n _handleSelect(time) {\n const state = this._store.getState();\n\n if (this.mode === 'single') {\n this._store.set({ selected: time });\n this.emit('cal:time-change', { value: time });\n if (this.display === 'popover') this.close();\n } else if (this.mode === 'multi') {\n const current = Array.isArray(state.selected) ? [...state.selected] : [];\n const idx = current.indexOf(time);\n if (idx >= 0) {\n current.splice(idx, 1);\n } else {\n current.push(time);\n }\n current.sort((a, b) => timeToMinutes(a) - timeToMinutes(b));\n this._store.set({ selected: current });\n this.emit('cal:time-change', { value: current });\n } else if (this.mode === 'range') {\n if (!state.rangeStart || (state.selected && typeof state.selected === 'object' && state.selected.start && state.selected.end)) {\n // Start new range\n this._store.set({ rangeStart: time, selected: null, hoverTime: null });\n } else {\n // Complete range\n let start = state.rangeStart;\n let end = time;\n if (timeToMinutes(start) > timeToMinutes(end)) [start, end] = [end, start];\n const value = { start, end };\n this._store.set({ selected: value, rangeStart: null, hoverTime: null });\n this.emit('cal:time-change', { value });\n if (this.display === 'popover') this.close();\n }\n }\n }\n\n _handleHover(time) {\n if (this.mode === 'range') {\n this._store.set({ hoverTime: time });\n }\n }\n\n // -- Lightweight hover highlight --\n _updateSlotHighlight(state) {\n const buttons = this.$$('.cal-time-slot');\n const { rangeStart, hoverTime, selected } = state;\n const rangeComplete = selected && typeof selected === 'object' && selected.start && selected.end;\n\n for (const btn of buttons) {\n const time = btn.dataset.time;\n if (!time || btn.disabled) continue;\n\n if (rangeStart && !rangeComplete && hoverTime) {\n const lo = timeToMinutes(rangeStart) < timeToMinutes(hoverTime) ? rangeStart : hoverTime;\n const hi = timeToMinutes(rangeStart) < timeToMinutes(hoverTime) ? hoverTime : rangeStart;\n const t = timeToMinutes(time);\n const inRange = t > timeToMinutes(lo) && t < timeToMinutes(hi);\n const isStart = time === rangeStart;\n const isEnd = time === hoverTime;\n\n btn.classList.toggle('cal-time-slot--range-start', isStart);\n btn.classList.toggle('cal-time-slot--range-end', isEnd);\n btn.classList.toggle('cal-time-slot--in-range', inRange);\n } else if (!rangeStart) {\n btn.classList.remove('cal-time-slot--range-start', 'cal-time-slot--range-end', 'cal-time-slot--in-range');\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 // -- Render --\n _renderTimepickerContent() {\n const state = this._store.getState();\n const container = document.createElement('div');\n container.classList.add('cal-timepicker');\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 const header = document.createElement('div');\n header.classList.add('cal-timepicker__header');\n header.textContent = 'Select Time';\n container.appendChild(header);\n\n if (this.loading) {\n container.appendChild(renderTimeGridSkeleton({ durationLabels: this.durationLabels }));\n } else {\n const slots = this._getEffectiveSlots();\n const grid = renderTimeGrid({\n slots,\n mode: this.mode,\n format: this.format,\n selected: state.selected,\n hoverTime: state.hoverTime,\n rangeStart: state.rangeStart,\n unavailableTimes: this._unavailableTimes,\n onSelect: (t) => this._handleSelect(t),\n onHover: (t) => this._handleHover(t),\n durationLabels: this.durationLabels,\n });\n container.appendChild(grid);\n }\n\n return container;\n }\n\n _formatTriggerText() {\n const state = this._store.getState();\n if (!state.selected) return null;\n if (this.mode === 'single' && typeof state.selected === 'string') {\n return state.selected;\n }\n if (this.mode === 'multi' && Array.isArray(state.selected) && state.selected.length) {\n return `${state.selected.length} time${state.selected.length > 1 ? 's' : ''} selected`;\n }\n if (this.mode === 'range' && typeof state.selected === 'object' && state.selected.start) {\n return `${state.selected.start} – ${state.selected.end}`;\n }\n return null;\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 = clockIcon;\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._renderTimepickerContent();\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._renderTimepickerContent());\n }\n\n this._rendering = false;\n }\n}\n","import { CalTimepicker } from '../components/timepicker/index.js';\n\nif (!customElements.get('cal-timepicker')) {\n customElements.define('cal-timepicker', CalTimepicker);\n}\n\nexport { CalTimepicker };\n"],"names":["CalendarBase","sheets","sheet","el","name","detail","type","message","opts","autoDismiss","dismissible","selector","createStore","initial","state","listeners","key","partial","prev","changed","fn","parseTime","str","trimmed","ampmMatch","hours","minutes","period","match24","formatTime","format","mm","timeToMinutes","t","minutesToTime","n","generateSlots","startTime","endTime","intervalMinutes","slots","startMin","endMin","m","generateDurationSlots","time","nextMin","endSlotTime","parsed","parsedEnd","fromText","toText","isTimeInRange","start","end","s","e","lo","hi","tokens","reset","animations","createPopover","trigger","content","onClose","panel","isOpen","position","triggerRect","panelHeight","spaceBelow","spaceAbove","open","outsideClick","escapeKey","close","_a","host","destroy","popoverStyles","renderTimeGrid","options","mode","selected","hoverTime","rangeStart","unavailableTimes","onSelect","onHover","durationLabels","grid","slot","btn","displayTime","timeSpan","labelSpan","isUnavailable","isSlotSelected","isRangeComplete","inRange","isStart","isEnd","timeGridStyles","renderTimeGridSkeleton","columns","rows","wrapper","count","pill","loadingSkeletonStyles","icons","renderStatusMessage","onDismiss","banner","icon","text","closeBtn","statusMessageStyles","clockIcon","componentStyles","CalTimepicker","val","a","b","valueAttr","_b","oldVal","newVal","current","idx","value","buttons","rangeComplete","container","header","root","children","child","label","popover"],"mappings":"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"}
1
+ {"version":3,"file":"timepicker.es.js","sources":["../src/core/base-component.js","../src/core/state.js","../src/core/times.js","../src/styles/tokens.js","../src/styles/reset.js","../src/styles/animations.js","../src/components/datepicker/popover.js","../src/components/timepicker/time-grid.js","../src/components/shared/loading-skeleton.js","../src/components/shared/status-message.js","../src/components/timepicker/index.js","../src/entries/timepicker.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 /** Reset selection state. Subclasses should override with specific logic. */\n clear() {}\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","/**\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 * Supports wrapping past midnight (e.g. start=\"22:00\", end=\"02:00\").\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 let endMin = timeToMinutes(endTime);\n // Wrap past midnight\n if (endMin <= startMin) endMin += 1440;\n for (let m = startMin; m <= endMin; m += intervalMinutes) {\n slots.push(minutesToTime(m % 1440));\n }\n return slots;\n}\n\n/**\n * Generate time slots with duration labels (e.g. \"09:00–09:30\").\n * Supports wrapping past midnight.\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 let endMin = timeToMinutes(endTime);\n // Wrap past midnight\n if (endMin <= startMin) endMin += 1440;\n for (let m = startMin; m <= endMin; m += intervalMinutes) {\n const time = minutesToTime(m % 1440);\n const nextMin = m + intervalMinutes;\n const endSlotTime = minutesToTime(Math.min(nextMin, endMin + intervalMinutes) % 1440);\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 * Supports wrapping past midnight for either range.\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 let a0 = timeToMinutes(startA);\n let a1 = timeToMinutes(endA);\n let b0 = timeToMinutes(startB);\n let b1 = timeToMinutes(endB);\n if (a1 <= a0) a1 += 1440;\n if (b1 <= b0) b1 += 1440;\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/**\n * Returns true if time is within [start, end] inclusive.\n * Supports wrapping past midnight (e.g. start=22:00, end=02:00).\n */\nexport function isTimeInRange(time, start, end) {\n const t = timeToMinutes(time);\n const s = timeToMinutes(start);\n const e = timeToMinutes(end);\n if (e >= s) {\n // Normal range\n return t >= s && t <= e;\n }\n // Wrapped range: e.g. 22:00–02:00\n return t >= s || t <= e;\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","/**\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 * 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 { generateSlots, generateDurationSlots, timeToMinutes } from '../../core/times.js';\nimport { tokens } from '../../styles/tokens.js';\nimport { reset } from '../../styles/reset.js';\nimport { animations } from '../../styles/animations.js';\nimport { createPopover, popoverStyles } from '../datepicker/popover.js';\nimport { renderTimeGrid, timeGridStyles } from './time-grid.js';\nimport { renderTimeGridSkeleton, loadingSkeletonStyles } from '../shared/loading-skeleton.js';\nimport { renderStatusMessage, statusMessageStyles } from '../shared/status-message.js';\n\nconst clockIcon = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"8\" cy=\"8\" r=\"6\"/><path d=\"M8 4.5V8l2.5 1.5\"/></svg>`;\n\nconst componentStyles = `\n .cal-timepicker {\n background: hsl(var(--cal-bg));\n border-radius: var(--cal-radius);\n user-select: none;\n min-width: 200px;\n }\n\n :host([display=\"inline\"]) .cal-timepicker {\n border: 1px solid hsl(var(--cal-border));\n padding: 12px;\n }\n\n .cal-timepicker__header {\n font-size: 14px;\n font-weight: 600;\n color: hsl(var(--cal-fg));\n margin-bottom: 8px;\n padding: 0 4px;\n }\n`;\n\nexport class CalTimepicker extends CalendarBase {\n static get styles() {\n return [tokens, reset, animations, timeGridStyles, popoverStyles, loadingSkeletonStyles, statusMessageStyles, componentStyles];\n }\n\n static get observedAttributes() {\n return ['mode', 'display', 'theme', 'start-time', 'end-time', 'interval', 'format', 'placeholder', 'value', 'duration-labels', 'loading', 'locale', 'min-time'];\n }\n\n constructor() {\n super();\n\n this._store = createStore({\n selected: null, // string | string[] | {start, end}\n rangeStart: null, // for range mode in-progress\n hoverTime: null,\n isOpen: false,\n statusType: null,\n statusMessage: null,\n statusDismissible: true,\n });\n\n this._slots = null; // explicit slots (highest priority)\n this._unavailableTimes = [];\n this._popover = null;\n this._unsubscribe = null;\n this._rendering = false;\n }\n\n // -- Attribute getters --\n get mode() { return this.getAttribute('mode') || 'single'; }\n get display() { return this.getAttribute('display') || 'inline'; }\n get placeholder() { return this.getAttribute('placeholder') || 'Select time'; }\n get startTime() { return this.getAttribute('start-time') || '09:00'; }\n get endTime() { return this.getAttribute('end-time') || '17:00'; }\n get interval() { return parseInt(this.getAttribute('interval') || '30', 10); }\n get format() { return this.getAttribute('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 get locale() { return this.getAttribute('locale') || undefined; }\n get minTime() { return this.getAttribute('min-time') || null; }\n\n // -- Properties --\n get slots() { return this._slots; }\n set slots(val) {\n this._slots = Array.isArray(val) ? val : null;\n if (this._initialized) this.render();\n }\n\n get unavailableTimes() { return this._unavailableTimes; }\n set unavailableTimes(val) {\n this._unavailableTimes = Array.isArray(val) ? val : [];\n if (this._initialized) this.render();\n }\n\n get value() {\n const state = this._store.getState();\n return state.selected;\n }\n\n set value(val) {\n if (this.mode === 'single' && typeof val === 'string') {\n this._store.set({ selected: val, rangeStart: null });\n } else if (this.mode === 'multi' && Array.isArray(val)) {\n this._store.set({ selected: [...val].sort((a, b) => timeToMinutes(a) - timeToMinutes(b)), rangeStart: null });\n } else if (this.mode === 'range' && val && typeof val === 'object') {\n this._store.set({ selected: { start: val.start, end: val.end }, rangeStart: null });\n } else {\n this._store.set({ selected: null, rangeStart: null });\n }\n }\n\n _getEffectiveSlots() {\n let slots;\n // Priority 1: explicit slots property\n if (this._slots) {\n slots = this._slots;\n } else if (this.durationLabels) {\n // Priority 2: auto-generate from attributes\n const durationSlots = generateDurationSlots(this.startTime, this.endTime, this.interval, this.format);\n slots = durationSlots.map((slot) => ({\n ...slot,\n available: !this._unavailableTimes.includes(slot.time),\n }));\n } else {\n const times = generateSlots(this.startTime, this.endTime, this.interval);\n slots = times.map((time) => ({\n time,\n available: !this._unavailableTimes.includes(time),\n }));\n }\n // Apply min-time constraint\n const mt = this.minTime;\n if (mt) {\n const minMin = timeToMinutes(mt);\n slots = slots.map((slot) => {\n const slotTime = typeof slot === 'string' ? slot : slot.time;\n if (timeToMinutes(slotTime) < minMin) {\n return typeof slot === 'string' ? { time: slot, available: false } : { ...slot, available: false };\n }\n return slot;\n });\n }\n return slots;\n }\n\n connectedCallback() {\n super.connectedCallback();\n this._unsubscribe = this._store.subscribe((state, prev) => {\n if (this._rendering) return;\n // Hover-only → lightweight update\n const hoverOnly = state.hoverTime !== prev.hoverTime\n && state.selected === prev.selected\n && state.rangeStart === prev.rangeStart\n && state.isOpen === prev.isOpen;\n hoverOnly ? this._updateSlotHighlight(state) : this.render();\n });\n\n // Parse initial value attribute\n const valueAttr = this.getAttribute('value');\n if (valueAttr) {\n if (this.mode === 'multi' && valueAttr.includes(',')) {\n this.value = valueAttr.split(',').map((t) => t.trim());\n } else if (this.mode === 'range' && valueAttr.includes('/')) {\n const [start, end] = valueAttr.split('/');\n this.value = { start: start.trim(), end: end.trim() };\n } else {\n this.value = valueAttr;\n }\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 (name === 'value' && this._initialized) {\n if (this.mode === 'multi' && newVal && newVal.includes(',')) {\n this.value = newVal.split(',').map((t) => t.trim());\n } else if (this.mode === 'range' && newVal && newVal.includes('/')) {\n const [start, end] = newVal.split('/');\n this.value = { start: start.trim(), end: end.trim() };\n } else {\n this.value = newVal;\n }\n }\n if (this._initialized) this.render();\n }\n\n // -- Selection --\n _handleSelect(time) {\n const state = this._store.getState();\n\n if (this.mode === 'single') {\n this._store.set({ selected: time });\n this.emit('cal:time-change', { value: time });\n if (this.display === 'popover') this.close();\n } else if (this.mode === 'multi') {\n const current = Array.isArray(state.selected) ? [...state.selected] : [];\n const idx = current.indexOf(time);\n if (idx >= 0) {\n current.splice(idx, 1);\n } else {\n current.push(time);\n }\n current.sort((a, b) => timeToMinutes(a) - timeToMinutes(b));\n this._store.set({ selected: current });\n this.emit('cal:time-change', { value: current });\n } else if (this.mode === 'range') {\n if (!state.rangeStart || (state.selected && typeof state.selected === 'object' && state.selected.start && state.selected.end)) {\n // Start new range\n this._store.set({ rangeStart: time, selected: null, hoverTime: null });\n } else {\n // Complete range\n let start = state.rangeStart;\n let end = time;\n if (timeToMinutes(start) > timeToMinutes(end)) [start, end] = [end, start];\n const value = { start, end };\n this._store.set({ selected: value, rangeStart: null, hoverTime: null });\n this.emit('cal:time-change', { value });\n if (this.display === 'popover') this.close();\n }\n }\n }\n\n _handleHover(time) {\n if (this.mode === 'range') {\n this._store.set({ hoverTime: time });\n }\n }\n\n // -- Lightweight hover highlight --\n _updateSlotHighlight(state) {\n const buttons = this.$$('.cal-time-slot');\n const { rangeStart, hoverTime, selected } = state;\n const rangeComplete = selected && typeof selected === 'object' && selected.start && selected.end;\n\n for (const btn of buttons) {\n const time = btn.dataset.time;\n if (!time || btn.disabled) continue;\n\n if (rangeStart && !rangeComplete && hoverTime) {\n const lo = timeToMinutes(rangeStart) < timeToMinutes(hoverTime) ? rangeStart : hoverTime;\n const hi = timeToMinutes(rangeStart) < timeToMinutes(hoverTime) ? hoverTime : rangeStart;\n const t = timeToMinutes(time);\n const inRange = t > timeToMinutes(lo) && t < timeToMinutes(hi);\n const isStart = time === rangeStart;\n const isEnd = time === hoverTime;\n\n btn.classList.toggle('cal-time-slot--range-start', isStart);\n btn.classList.toggle('cal-time-slot--range-end', isEnd);\n btn.classList.toggle('cal-time-slot--in-range', inRange);\n } else if (!rangeStart) {\n btn.classList.remove('cal-time-slot--range-start', 'cal-time-slot--range-end', 'cal-time-slot--in-range');\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 clear() {\n this._store.set({\n selected: null,\n rangeStart: null,\n hoverTime: null,\n });\n this.emit('cal:time-change', { value: null });\n }\n\n // -- Render --\n _renderTimepickerContent() {\n const state = this._store.getState();\n const container = document.createElement('div');\n container.classList.add('cal-timepicker');\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 const header = document.createElement('div');\n header.classList.add('cal-timepicker__header');\n header.textContent = 'Select Time';\n container.appendChild(header);\n\n if (this.loading) {\n container.appendChild(renderTimeGridSkeleton({ durationLabels: this.durationLabels }));\n } else {\n const slots = this._getEffectiveSlots();\n const grid = renderTimeGrid({\n slots,\n mode: this.mode,\n format: this.format,\n selected: state.selected,\n hoverTime: state.hoverTime,\n rangeStart: state.rangeStart,\n unavailableTimes: this._unavailableTimes,\n onSelect: (t) => this._handleSelect(t),\n onHover: (t) => this._handleHover(t),\n durationLabels: this.durationLabels,\n });\n container.appendChild(grid);\n }\n\n return container;\n }\n\n _formatTriggerText() {\n const state = this._store.getState();\n if (!state.selected) return null;\n if (this.mode === 'single' && typeof state.selected === 'string') {\n return state.selected;\n }\n if (this.mode === 'multi' && Array.isArray(state.selected) && state.selected.length) {\n return `${state.selected.length} time${state.selected.length > 1 ? 's' : ''} selected`;\n }\n if (this.mode === 'range' && typeof state.selected === 'object' && state.selected.start) {\n return `${state.selected.start} – ${state.selected.end}`;\n }\n return null;\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 = clockIcon;\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._renderTimepickerContent();\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._renderTimepickerContent());\n }\n\n this._rendering = false;\n }\n}\n","import { CalTimepicker } from '../components/timepicker/index.js';\n\nif (!customElements.get('cal-timepicker')) {\n customElements.define('cal-timepicker', CalTimepicker);\n}\n\nexport { CalTimepicker };\n"],"names":["CalendarBase","sheets","s","sheet","el","name","detail","type","message","opts","autoDismiss","dismissible","selector","createStore","initial","state","listeners","key","partial","prev","changed","fn","parseTime","str","trimmed","ampmMatch","hours","minutes","period","match24","formatTime","format","mm","timeToMinutes","t","minutesToTime","n","generateSlots","startTime","endTime","intervalMinutes","slots","startMin","endMin","m","generateDurationSlots","time","nextMin","endSlotTime","parsed","parsedEnd","fromText","toText","isTimeInRange","start","end","e","tokens","reset","animations","createPopover","trigger","content","onClose","panel","isOpen","position","triggerRect","panelHeight","spaceBelow","spaceAbove","open","outsideClick","escapeKey","close","_a","host","destroy","popoverStyles","renderTimeGrid","options","mode","selected","hoverTime","rangeStart","unavailableTimes","onSelect","onHover","durationLabels","grid","slot","btn","displayTime","timeSpan","labelSpan","isUnavailable","isSlotSelected","isRangeComplete","inRange","isStart","isEnd","timeGridStyles","renderTimeGridSkeleton","columns","rows","wrapper","count","pill","loadingSkeletonStyles","icons","renderStatusMessage","onDismiss","banner","icon","text","closeBtn","statusMessageStyles","clockIcon","componentStyles","CalTimepicker","val","b","mt","minMin","slotTime","valueAttr","_b","oldVal","newVal","current","idx","a","value","buttons","rangeComplete","lo","hi","container","header","root","children","child","label","popover"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- (function(b,v){typeof exports=="object"&&typeof module<"u"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(b=typeof globalThis<"u"?globalThis:b||self,v(b.CalTimepicker={}))})(this,(function(b){"use strict";class v extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._initialized=!1}static get styles(){return[]}connectedCallback(){this._initialized||(this._adoptStyles(),this._initialized=!0),this.render()}_adoptStyles(){const e=this.constructor.styles;if(e.length)if("adoptedStyleSheets"in this.shadowRoot)this.shadowRoot.adoptedStyleSheets=e.map(s=>{if(s instanceof CSSStyleSheet)return s;const t=new CSSStyleSheet;return t.replaceSync(s),t});else for(const s of e){const t=document.createElement("style");t.textContent=s instanceof CSSStyleSheet?"":s,this.shadowRoot.prepend(t)}}render(){}emit(e,s={}){this.dispatchEvent(new CustomEvent(e,{detail:s,bubbles:!0,composed:!0}))}showStatus(e,s,t={}){if(!this._store)return;const{autoDismiss:a,dismissible:i=!0}=t;clearTimeout(this._statusTimer),this._store.set({statusType:e,statusMessage:s,statusDismissible:i}),this.emit("cal:status",{type:e,message:s}),a&&a>0&&(this._statusTimer=setTimeout(()=>this.clearStatus(),a))}clearStatus(){this._store&&(clearTimeout(this._statusTimer),this._store.set({statusType:null,statusMessage:null,statusDismissible:!0}),this.emit("cal:status",{type:null,message:null}))}$(e){return this.shadowRoot.querySelector(e)}$$(e){return this.shadowRoot.querySelectorAll(e)}}function E(r){let e={...r};const s=new Set;return{get(t){return e[t]},set(t){const a=e;e={...e,...t};let i=!1;for(const l of Object.keys(t))if(a[l]!==e[l]){i=!0;break}if(i)for(const l of s)l(e,a)},getState(){return e},subscribe(t){return s.add(t),()=>s.delete(t)}}}function x(r){if(!r||typeof r!="string")return null;const e=r.trim().toUpperCase(),s=e.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/);if(s){let a=parseInt(s[1],10);const i=parseInt(s[2],10),l=s[3];return l==="AM"&&a===12&&(a=0),l==="PM"&&a!==12&&(a+=12),{hours:a,minutes:i}}const t=e.match(/^(\d{1,2}):(\d{2})$/);return t?{hours:parseInt(t[1],10),minutes:parseInt(t[2],10)}:null}function _(r,e,s="24h"){const t=String(e).padStart(2,"0");if(s==="12h"){const a=r>=12?"PM":"AM";return`${r%12||12}:${t} ${a}`}return`${String(r).padStart(2,"0")}:${t}`}function g(r){const e=x(r);return e?e.hours*60+e.minutes:0}function S(r){const e=Math.floor(r/60)%24,s=r%60;return`${String(e).padStart(2,"0")}:${String(s).padStart(2,"0")}`}function M(r,e,s){const t=[],a=g(r),i=g(e);for(let l=a;l<=i;l+=s)t.push(S(l));return t}function z(r,e,s,t="24h"){const a=[],i=g(r),l=g(e);for(let c=i;c<=l;c+=s){const u=S(c),h=c+s,m=S(Math.min(h,l+s)),d=x(u),n=x(m),o=d?_(d.hours,d.minutes,t):u,p=n?_(n.hours,n.minutes,t):m;a.push({time:u,displayText:`${o}–${p}`})}return a}function w(r,e,s){const t=g(r),a=g(e),i=g(s),l=Math.min(a,i),c=Math.max(a,i);return t>=l&&t<=c}const $=`
1
+ (function(b,v){typeof exports=="object"&&typeof module<"u"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(b=typeof globalThis<"u"?globalThis:b||self,v(b.CalTimepicker={}))})(this,(function(b){"use strict";class v extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._initialized=!1}static get styles(){return[]}connectedCallback(){this._initialized||(this._adoptStyles(),this._initialized=!0),this.render()}_adoptStyles(){const e=this.constructor.styles;if(e.length)if("adoptedStyleSheets"in this.shadowRoot)this.shadowRoot.adoptedStyleSheets=e.map(a=>{if(a instanceof CSSStyleSheet)return a;const t=new CSSStyleSheet;return t.replaceSync(a),t});else for(const a of e){const t=document.createElement("style");t.textContent=a instanceof CSSStyleSheet?"":a,this.shadowRoot.prepend(t)}}render(){}clear(){}emit(e,a={}){this.dispatchEvent(new CustomEvent(e,{detail:a,bubbles:!0,composed:!0}))}showStatus(e,a,t={}){if(!this._store)return;const{autoDismiss:s,dismissible:i=!0}=t;clearTimeout(this._statusTimer),this._store.set({statusType:e,statusMessage:a,statusDismissible:i}),this.emit("cal:status",{type:e,message:a}),s&&s>0&&(this._statusTimer=setTimeout(()=>this.clearStatus(),s))}clearStatus(){this._store&&(clearTimeout(this._statusTimer),this._store.set({statusType:null,statusMessage:null,statusDismissible:!0}),this.emit("cal:status",{type:null,message:null}))}$(e){return this.shadowRoot.querySelector(e)}$$(e){return this.shadowRoot.querySelectorAll(e)}}function E(r){let e={...r};const a=new Set;return{get(t){return e[t]},set(t){const s=e;e={...e,...t};let i=!1;for(const l of Object.keys(t))if(s[l]!==e[l]){i=!0;break}if(i)for(const l of a)l(e,s)},getState(){return e},subscribe(t){return a.add(t),()=>a.delete(t)}}}function x(r){if(!r||typeof r!="string")return null;const e=r.trim().toUpperCase(),a=e.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/);if(a){let s=parseInt(a[1],10);const i=parseInt(a[2],10),l=a[3];return l==="AM"&&s===12&&(s=0),l==="PM"&&s!==12&&(s+=12),{hours:s,minutes:i}}const t=e.match(/^(\d{1,2}):(\d{2})$/);return t?{hours:parseInt(t[1],10),minutes:parseInt(t[2],10)}:null}function _(r,e,a="24h"){const t=String(e).padStart(2,"0");if(a==="12h"){const s=r>=12?"PM":"AM";return`${r%12||12}:${t} ${s}`}return`${String(r).padStart(2,"0")}:${t}`}function u(r){const e=x(r);return e?e.hours*60+e.minutes:0}function S(r){const e=Math.floor(r/60)%24,a=r%60;return`${String(e).padStart(2,"0")}:${String(a).padStart(2,"0")}`}function M(r,e,a){const t=[],s=u(r);let i=u(e);i<=s&&(i+=1440);for(let l=s;l<=i;l+=a)t.push(S(l%1440));return t}function z(r,e,a,t="24h"){const s=[],i=u(r);let l=u(e);l<=i&&(l+=1440);for(let c=i;c<=l;c+=a){const g=S(c%1440),h=c+a,m=S(Math.min(h,l+a)%1440),d=x(g),n=x(m),o=d?_(d.hours,d.minutes,t):g,p=n?_(n.hours,n.minutes,t):m;s.push({time:g,displayText:`${o}–${p}`})}return s}function w(r,e,a){const t=u(r),s=u(e),i=u(a);return i>=s?t>=s&&t<=i:t>=s||t<=i}const $=`
2
2
  :host {
3
3
  /* Light theme (default) */
4
4
  --cal-bg: 0 0% 100%;
@@ -271,7 +271,7 @@
271
271
  .cal-skeleton--rect {
272
272
  border-radius: var(--cal-radius-sm);
273
273
  }
274
- `;function R({trigger:r,content:e,onClose:s}){const t=document.createElement("div");t.classList.add("cal-popover"),t.setAttribute("role","dialog"),t.setAttribute("aria-modal","false"),t.style.display="none",t.appendChild(e);let a=!1;function i(){t.classList.remove("cal-popover--above");const d=r.getBoundingClientRect(),n=t.offsetHeight,o=window.innerHeight-d.bottom,p=d.top;o<n+8&&p>o?(t.classList.add("cal-popover--above"),t.style.top="auto",t.style.bottom="100%",t.style.marginBottom="4px",t.style.marginTop="0"):(t.style.top="100%",t.style.bottom="auto",t.style.marginTop="4px",t.style.marginBottom="0")}function l(){a||(a=!0,t.style.display="",t.classList.add("cal-animate-slide-up"),requestAnimationFrame(()=>i()),document.addEventListener("click",u,!0),document.addEventListener("keydown",h,!0))}function c(){a&&(a=!1,t.style.display="none",t.classList.remove("cal-animate-slide-up"),document.removeEventListener("click",u,!0),document.removeEventListener("keydown",h,!0),s==null||s())}function u(d){var o;const n=(o=r.getRootNode())==null?void 0:o.host;n&&!n.contains(d.target)&&d.target!==n&&c()}function h(d){d.key==="Escape"&&(d.stopPropagation(),c())}function m(){a&&(a=!1,t.style.display="none",t.classList.remove("cal-animate-slide-up")),document.removeEventListener("click",u,!0),document.removeEventListener("keydown",h,!0)}return{panel:t,open:l,close:c,destroy:m,get isOpen(){return a}}}const j=`
274
+ `;function R({trigger:r,content:e,onClose:a}){const t=document.createElement("div");t.classList.add("cal-popover"),t.setAttribute("role","dialog"),t.setAttribute("aria-modal","false"),t.style.display="none",t.appendChild(e);let s=!1;function i(){t.classList.remove("cal-popover--above");const d=r.getBoundingClientRect(),n=t.offsetHeight,o=window.innerHeight-d.bottom,p=d.top;o<n+8&&p>o?(t.classList.add("cal-popover--above"),t.style.top="auto",t.style.bottom="100%",t.style.marginBottom="4px",t.style.marginTop="0"):(t.style.top="100%",t.style.bottom="auto",t.style.marginTop="4px",t.style.marginBottom="0")}function l(){s||(s=!0,t.style.display="",t.classList.add("cal-animate-slide-up"),requestAnimationFrame(()=>i()),document.addEventListener("click",g,!0),document.addEventListener("keydown",h,!0))}function c(){s&&(s=!1,t.style.display="none",t.classList.remove("cal-animate-slide-up"),document.removeEventListener("click",g,!0),document.removeEventListener("keydown",h,!0),a==null||a())}function g(d){var o;const n=(o=r.getRootNode())==null?void 0:o.host;n&&!n.contains(d.target)&&d.target!==n&&c()}function h(d){d.key==="Escape"&&(d.stopPropagation(),c())}function m(){s&&(s=!1,t.style.display="none",t.classList.remove("cal-animate-slide-up")),document.removeEventListener("click",g,!0),document.removeEventListener("keydown",h,!0)}return{panel:t,open:l,close:c,destroy:m,get isOpen(){return s}}}const j=`
275
275
  .cal-popover-wrapper {
276
276
  position: relative;
277
277
  display: inline-block;
@@ -316,7 +316,7 @@
316
316
  display: flex;
317
317
  color: hsl(var(--cal-fg-muted));
318
318
  }
319
- `;function H(r){const{slots:e=[],mode:s="single",format:t="24h",selected:a,hoverTime:i,rangeStart:l,unavailableTimes:c=[],onSelect:u,onHover:h,durationLabels:m=!1}=r,d=document.createElement("div");d.classList.add("cal-time-grid"),m&&d.classList.add("cal-time-grid--duration"),d.setAttribute("role","listbox"),s==="multi"&&d.setAttribute("aria-multiselectable","true");for(const n of e){const o=document.createElement("button");o.classList.add("cal-time-slot"),o.setAttribute("role","option"),o.dataset.time=n.time;const p=x(n.time),F=n.displayText?n.displayText:p?_(p.hours,p.minutes,t):n.time,T=document.createElement("span");if(T.classList.add("cal-time-slot__time"),T.textContent=F,o.appendChild(T),n.label){const f=document.createElement("span");f.classList.add("cal-time-slot__label"),f.textContent=n.label,o.appendChild(f)}const A=n.available===!1||c.includes(n.time);if(A&&(o.classList.add("cal-time-slot--unavailable"),o.disabled=!0,o.setAttribute("aria-disabled","true")),I(n.time,a,s)?(o.classList.add("cal-time-slot--selected"),o.setAttribute("aria-selected","true")):o.setAttribute("aria-selected","false"),s==="range"&&l&&!P(a)&&i){const f=w(n.time,l,i),k=n.time===l,y=n.time===i;f&&!k&&!y&&o.classList.add("cal-time-slot--in-range"),k&&o.classList.add("cal-time-slot--range-start"),y&&o.classList.add("cal-time-slot--range-end")}else if(s==="range"&&a&&typeof a=="object"&&a.start&&a.end){const f=w(n.time,a.start,a.end),k=n.time===a.start,y=n.time===a.end;k&&o.classList.add("cal-time-slot--range-start","cal-time-slot--selected"),y&&o.classList.add("cal-time-slot--range-end","cal-time-slot--selected"),f&&!k&&!y&&o.classList.add("cal-time-slot--in-range")}A||(o.addEventListener("click",()=>u==null?void 0:u(n.time)),o.addEventListener("mouseenter",()=>h==null?void 0:h(n.time))),d.appendChild(o)}return d.addEventListener("mouseleave",()=>h==null?void 0:h(null)),d}function I(r,e,s){return e?s==="single"?e===r:s==="multi"?Array.isArray(e)&&e.includes(r):s==="range"&&typeof e=="object"&&e.start&&e.end?e.start===r||e.end===r:!1:!1}function P(r){return r&&typeof r=="object"&&r.start&&r.end}const D=`
319
+ `;function H(r){const{slots:e=[],mode:a="single",format:t="24h",selected:s,hoverTime:i,rangeStart:l,unavailableTimes:c=[],onSelect:g,onHover:h,durationLabels:m=!1}=r,d=document.createElement("div");d.classList.add("cal-time-grid"),m&&d.classList.add("cal-time-grid--duration"),d.setAttribute("role","listbox"),a==="multi"&&d.setAttribute("aria-multiselectable","true");for(const n of e){const o=document.createElement("button");o.classList.add("cal-time-slot"),o.setAttribute("role","option"),o.dataset.time=n.time;const p=x(n.time),F=n.displayText?n.displayText:p?_(p.hours,p.minutes,t):n.time,T=document.createElement("span");if(T.classList.add("cal-time-slot__time"),T.textContent=F,o.appendChild(T),n.label){const f=document.createElement("span");f.classList.add("cal-time-slot__label"),f.textContent=n.label,o.appendChild(f)}const A=n.available===!1||c.includes(n.time);if(A&&(o.classList.add("cal-time-slot--unavailable"),o.disabled=!0,o.setAttribute("aria-disabled","true")),I(n.time,s,a)?(o.classList.add("cal-time-slot--selected"),o.setAttribute("aria-selected","true")):o.setAttribute("aria-selected","false"),a==="range"&&l&&!P(s)&&i){const f=w(n.time,l,i),k=n.time===l,y=n.time===i;f&&!k&&!y&&o.classList.add("cal-time-slot--in-range"),k&&o.classList.add("cal-time-slot--range-start"),y&&o.classList.add("cal-time-slot--range-end")}else if(a==="range"&&s&&typeof s=="object"&&s.start&&s.end){const f=w(n.time,s.start,s.end),k=n.time===s.start,y=n.time===s.end;k&&o.classList.add("cal-time-slot--range-start","cal-time-slot--selected"),y&&o.classList.add("cal-time-slot--range-end","cal-time-slot--selected"),f&&!k&&!y&&o.classList.add("cal-time-slot--in-range")}A||(o.addEventListener("click",()=>g==null?void 0:g(n.time)),o.addEventListener("mouseenter",()=>h==null?void 0:h(n.time))),d.appendChild(o)}return d.addEventListener("mouseleave",()=>h==null?void 0:h(null)),d}function I(r,e,a){return e?a==="single"?e===r:a==="multi"?Array.isArray(e)&&e.includes(r):a==="range"&&typeof e=="object"&&e.start&&e.end?e.start===r||e.end===r:!1:!1}function P(r){return r&&typeof r=="object"&&r.start&&r.end}const D=`
320
320
  .cal-time-grid {
321
321
  display: grid;
322
322
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
@@ -398,7 +398,7 @@
398
398
  .cal-time-grid--duration .cal-time-slot {
399
399
  font-size: 12px;
400
400
  }
401
- `;function X({columns:r=3,rows:e=4,durationLabels:s=!1}={}){const t=document.createElement("div");t.setAttribute("role","status"),t.setAttribute("aria-label","Loading..."),t.classList.add("cal-skeleton-time-grid"),s&&t.classList.add("cal-skeleton-time-grid--duration");const a=r*e;for(let i=0;i<a;i++){const l=document.createElement("div");l.classList.add("cal-skeleton"),t.appendChild(l)}return t}const q=`
401
+ `;function X({columns:r=3,rows:e=4,durationLabels:a=!1}={}){const t=document.createElement("div");t.setAttribute("role","status"),t.setAttribute("aria-label","Loading..."),t.classList.add("cal-skeleton-time-grid"),a&&t.classList.add("cal-skeleton-time-grid--duration");const s=r*e;for(let i=0;i<s;i++){const l=document.createElement("div");l.classList.add("cal-skeleton"),t.appendChild(l)}return t}const q=`
402
402
  .cal-skeleton-time-grid {
403
403
  display: grid;
404
404
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
@@ -431,7 +431,7 @@
431
431
  aspect-ratio: 1;
432
432
  border-radius: var(--cal-radius-sm) !important;
433
433
  }
434
- `,L={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>',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>',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>',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>'};function G({type:r="info",message:e,dismissible:s=!0,onDismiss:t}){const a=document.createElement("div");a.classList.add("cal-status",`cal-status--${r}`,"cal-animate-slide-up"),a.setAttribute("role",r==="error"?"alert":"status"),a.setAttribute("aria-live",r==="error"?"assertive":"polite");const i=document.createElement("span");i.classList.add("cal-status__icon"),i.innerHTML=L[r]||L.info,a.appendChild(i);const l=document.createElement("span");if(l.classList.add("cal-status__text"),l.textContent=e,a.appendChild(l),s){const c=document.createElement("button");c.classList.add("cal-status__close"),c.setAttribute("aria-label","Dismiss"),c.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>',c.addEventListener("click",()=>t==null?void 0:t()),a.appendChild(c)}return a}const N=`
434
+ `,L={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>',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>',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>',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>'};function G({type:r="info",message:e,dismissible:a=!0,onDismiss:t}){const s=document.createElement("div");s.classList.add("cal-status",`cal-status--${r}`,"cal-animate-slide-up"),s.setAttribute("role",r==="error"?"alert":"status"),s.setAttribute("aria-live",r==="error"?"assertive":"polite");const i=document.createElement("span");i.classList.add("cal-status__icon"),i.innerHTML=L[r]||L.info,s.appendChild(i);const l=document.createElement("span");if(l.classList.add("cal-status__text"),l.textContent=e,s.appendChild(l),a){const c=document.createElement("button");c.classList.add("cal-status__close"),c.setAttribute("aria-label","Dismiss"),c.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>',c.addEventListener("click",()=>t==null?void 0:t()),s.appendChild(c)}return s}const N=`
435
435
  .cal-status {
436
436
  display: flex;
437
437
  align-items: center;
@@ -513,5 +513,5 @@
513
513
  margin-bottom: 8px;
514
514
  padding: 0 4px;
515
515
  }
516
- `;class C extends v{static get styles(){return[$,O,B,D,j,q,N,U]}static get observedAttributes(){return["mode","display","theme","start-time","end-time","interval","format","placeholder","value","duration-labels","loading"]}constructor(){super(),this._store=E({selected:null,rangeStart:null,hoverTime:null,isOpen:!1,statusType:null,statusMessage:null,statusDismissible:!0}),this._slots=null,this._unavailableTimes=[],this._popover=null,this._unsubscribe=null,this._rendering=!1}get mode(){return this.getAttribute("mode")||"single"}get display(){return this.getAttribute("display")||"inline"}get placeholder(){return this.getAttribute("placeholder")||"Select time"}get startTime(){return this.getAttribute("start-time")||"09:00"}get endTime(){return this.getAttribute("end-time")||"17:00"}get interval(){return parseInt(this.getAttribute("interval")||"30",10)}get format(){return this.getAttribute("format")||"24h"}get durationLabels(){return this.hasAttribute("duration-labels")}get loading(){return this.hasAttribute("loading")}set loading(e){e?this.setAttribute("loading",""):this.removeAttribute("loading")}get slots(){return this._slots}set slots(e){this._slots=Array.isArray(e)?e:null,this._initialized&&this.render()}get unavailableTimes(){return this._unavailableTimes}set unavailableTimes(e){this._unavailableTimes=Array.isArray(e)?e:[],this._initialized&&this.render()}get value(){return this._store.getState().selected}set value(e){this.mode==="single"&&typeof e=="string"?this._store.set({selected:e,rangeStart:null}):this.mode==="multi"&&Array.isArray(e)?this._store.set({selected:[...e].sort((s,t)=>g(s)-g(t)),rangeStart:null}):this.mode==="range"&&e&&typeof e=="object"?this._store.set({selected:{start:e.start,end:e.end},rangeStart:null}):this._store.set({selected:null,rangeStart:null})}_getEffectiveSlots(){return this._slots?this._slots:this.durationLabels?z(this.startTime,this.endTime,this.interval,this.format).map(t=>({...t,available:!this._unavailableTimes.includes(t.time)})):M(this.startTime,this.endTime,this.interval).map(s=>({time:s,available:!this._unavailableTimes.includes(s)}))}connectedCallback(){super.connectedCallback(),this._unsubscribe=this._store.subscribe((s,t)=>{if(this._rendering)return;s.hoverTime!==t.hoverTime&&s.selected===t.selected&&s.rangeStart===t.rangeStart&&s.isOpen===t.isOpen?this._updateSlotHighlight(s):this.render()});const e=this.getAttribute("value");if(e)if(this.mode==="multi"&&e.includes(","))this.value=e.split(",").map(s=>s.trim());else if(this.mode==="range"&&e.includes("/")){const[s,t]=e.split("/");this.value={start:s.trim(),end:t.trim()}}else this.value=e}disconnectedCallback(){var e,s;(e=this._unsubscribe)==null||e.call(this),(s=this._popover)==null||s.destroy(),clearTimeout(this._statusTimer)}attributeChangedCallback(e,s,t){if(s!==t){if(e==="value"&&this._initialized)if(this.mode==="multi"&&t&&t.includes(","))this.value=t.split(",").map(a=>a.trim());else if(this.mode==="range"&&t&&t.includes("/")){const[a,i]=t.split("/");this.value={start:a.trim(),end:i.trim()}}else this.value=t;this._initialized&&this.render()}}_handleSelect(e){const s=this._store.getState();if(this.mode==="single")this._store.set({selected:e}),this.emit("cal:time-change",{value:e}),this.display==="popover"&&this.close();else if(this.mode==="multi"){const t=Array.isArray(s.selected)?[...s.selected]:[],a=t.indexOf(e);a>=0?t.splice(a,1):t.push(e),t.sort((i,l)=>g(i)-g(l)),this._store.set({selected:t}),this.emit("cal:time-change",{value:t})}else if(this.mode==="range")if(!s.rangeStart||s.selected&&typeof s.selected=="object"&&s.selected.start&&s.selected.end)this._store.set({rangeStart:e,selected:null,hoverTime:null});else{let t=s.rangeStart,a=e;g(t)>g(a)&&([t,a]=[a,t]);const i={start:t,end:a};this._store.set({selected:i,rangeStart:null,hoverTime:null}),this.emit("cal:time-change",{value:i}),this.display==="popover"&&this.close()}}_handleHover(e){this.mode==="range"&&this._store.set({hoverTime:e})}_updateSlotHighlight(e){const s=this.$$(".cal-time-slot"),{rangeStart:t,hoverTime:a,selected:i}=e,l=i&&typeof i=="object"&&i.start&&i.end;for(const c of s){const u=c.dataset.time;if(!(!u||c.disabled))if(t&&!l&&a){const h=g(t)<g(a)?t:a,m=g(t)<g(a)?a:t,d=g(u),n=d>g(h)&&d<g(m),o=u===t,p=u===a;c.classList.toggle("cal-time-slot--range-start",o),c.classList.toggle("cal-time-slot--range-end",p),c.classList.toggle("cal-time-slot--in-range",n)}else t||c.classList.remove("cal-time-slot--range-start","cal-time-slot--range-end","cal-time-slot--in-range")}}open(){this._popover&&(this._popover.open(),this._store.set({isOpen:!0}),this.emit("cal:open"))}close(){this._popover&&(this._popover.close(),this._store.set({isOpen:!1}),this.emit("cal:close"))}_renderTimepickerContent(){const e=this._store.getState(),s=document.createElement("div");s.classList.add("cal-timepicker"),e.statusType&&e.statusMessage&&s.appendChild(G({type:e.statusType,message:e.statusMessage,dismissible:e.statusDismissible,onDismiss:()=>this.clearStatus()}));const t=document.createElement("div");if(t.classList.add("cal-timepicker__header"),t.textContent="Select Time",s.appendChild(t),this.loading)s.appendChild(X({durationLabels:this.durationLabels}));else{const a=this._getEffectiveSlots(),i=H({slots:a,mode:this.mode,format:this.format,selected:e.selected,hoverTime:e.hoverTime,rangeStart:e.rangeStart,unavailableTimes:this._unavailableTimes,onSelect:l=>this._handleSelect(l),onHover:l=>this._handleHover(l),durationLabels:this.durationLabels});s.appendChild(i)}return s}_formatTriggerText(){const e=this._store.getState();return e.selected?this.mode==="single"&&typeof e.selected=="string"?e.selected:this.mode==="multi"&&Array.isArray(e.selected)&&e.selected.length?`${e.selected.length} time${e.selected.length>1?"s":""} selected`:this.mode==="range"&&typeof e.selected=="object"&&e.selected.start?`${e.selected.start} – ${e.selected.end}`:null:null}render(){var t;if(this._rendering)return;this._rendering=!0;const e=this.shadowRoot,s=[...e.childNodes];for(const a of s)a.nodeName!=="STYLE"&&!(a instanceof CSSStyleSheet)&&e.removeChild(a);if((t=this._popover)==null||t.destroy(),this._popover=null,this.display==="popover"){const a=document.createElement("div");a.classList.add("cal-popover-wrapper");const i=document.createElement("button");i.classList.add("cal-trigger");const l=document.createElement("span");l.classList.add("cal-trigger__icon"),l.innerHTML=Y,i.appendChild(l);const c=this._formatTriggerText(),u=document.createElement("span");c?u.textContent=c:(u.textContent=this.placeholder,u.classList.add("cal-trigger--placeholder")),i.appendChild(u),a.appendChild(i);const h=this._renderTimepickerContent(),m=R({trigger:i,content:h,onClose:()=>{this._store.set({isOpen:!1}),this.emit("cal:close")}});a.appendChild(m.panel),e.appendChild(a),i.addEventListener("click",d=>{d.stopPropagation(),m.isOpen?this.close():this.open()}),this._popover=m,this._store.get("isOpen")&&m.open()}else e.appendChild(this._renderTimepickerContent());this._rendering=!1}}customElements.get("cal-timepicker")||customElements.define("cal-timepicker",C),b.CalTimepicker=C,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})}));
516
+ `;class C extends v{static get styles(){return[$,O,B,D,j,q,N,U]}static get observedAttributes(){return["mode","display","theme","start-time","end-time","interval","format","placeholder","value","duration-labels","loading","locale","min-time"]}constructor(){super(),this._store=E({selected:null,rangeStart:null,hoverTime:null,isOpen:!1,statusType:null,statusMessage:null,statusDismissible:!0}),this._slots=null,this._unavailableTimes=[],this._popover=null,this._unsubscribe=null,this._rendering=!1}get mode(){return this.getAttribute("mode")||"single"}get display(){return this.getAttribute("display")||"inline"}get placeholder(){return this.getAttribute("placeholder")||"Select time"}get startTime(){return this.getAttribute("start-time")||"09:00"}get endTime(){return this.getAttribute("end-time")||"17:00"}get interval(){return parseInt(this.getAttribute("interval")||"30",10)}get format(){return this.getAttribute("format")||"24h"}get durationLabels(){return this.hasAttribute("duration-labels")}get loading(){return this.hasAttribute("loading")}set loading(e){e?this.setAttribute("loading",""):this.removeAttribute("loading")}get locale(){return this.getAttribute("locale")||void 0}get minTime(){return this.getAttribute("min-time")||null}get slots(){return this._slots}set slots(e){this._slots=Array.isArray(e)?e:null,this._initialized&&this.render()}get unavailableTimes(){return this._unavailableTimes}set unavailableTimes(e){this._unavailableTimes=Array.isArray(e)?e:[],this._initialized&&this.render()}get value(){return this._store.getState().selected}set value(e){this.mode==="single"&&typeof e=="string"?this._store.set({selected:e,rangeStart:null}):this.mode==="multi"&&Array.isArray(e)?this._store.set({selected:[...e].sort((a,t)=>u(a)-u(t)),rangeStart:null}):this.mode==="range"&&e&&typeof e=="object"?this._store.set({selected:{start:e.start,end:e.end},rangeStart:null}):this._store.set({selected:null,rangeStart:null})}_getEffectiveSlots(){let e;this._slots?e=this._slots:this.durationLabels?e=z(this.startTime,this.endTime,this.interval,this.format).map(s=>({...s,available:!this._unavailableTimes.includes(s.time)})):e=M(this.startTime,this.endTime,this.interval).map(s=>({time:s,available:!this._unavailableTimes.includes(s)}));const a=this.minTime;if(a){const t=u(a);e=e.map(s=>{const i=typeof s=="string"?s:s.time;return u(i)<t?typeof s=="string"?{time:s,available:!1}:{...s,available:!1}:s})}return e}connectedCallback(){super.connectedCallback(),this._unsubscribe=this._store.subscribe((a,t)=>{if(this._rendering)return;a.hoverTime!==t.hoverTime&&a.selected===t.selected&&a.rangeStart===t.rangeStart&&a.isOpen===t.isOpen?this._updateSlotHighlight(a):this.render()});const e=this.getAttribute("value");if(e)if(this.mode==="multi"&&e.includes(","))this.value=e.split(",").map(a=>a.trim());else if(this.mode==="range"&&e.includes("/")){const[a,t]=e.split("/");this.value={start:a.trim(),end:t.trim()}}else this.value=e}disconnectedCallback(){var e,a;(e=this._unsubscribe)==null||e.call(this),(a=this._popover)==null||a.destroy(),clearTimeout(this._statusTimer)}attributeChangedCallback(e,a,t){if(a!==t){if(e==="value"&&this._initialized)if(this.mode==="multi"&&t&&t.includes(","))this.value=t.split(",").map(s=>s.trim());else if(this.mode==="range"&&t&&t.includes("/")){const[s,i]=t.split("/");this.value={start:s.trim(),end:i.trim()}}else this.value=t;this._initialized&&this.render()}}_handleSelect(e){const a=this._store.getState();if(this.mode==="single")this._store.set({selected:e}),this.emit("cal:time-change",{value:e}),this.display==="popover"&&this.close();else if(this.mode==="multi"){const t=Array.isArray(a.selected)?[...a.selected]:[],s=t.indexOf(e);s>=0?t.splice(s,1):t.push(e),t.sort((i,l)=>u(i)-u(l)),this._store.set({selected:t}),this.emit("cal:time-change",{value:t})}else if(this.mode==="range")if(!a.rangeStart||a.selected&&typeof a.selected=="object"&&a.selected.start&&a.selected.end)this._store.set({rangeStart:e,selected:null,hoverTime:null});else{let t=a.rangeStart,s=e;u(t)>u(s)&&([t,s]=[s,t]);const i={start:t,end:s};this._store.set({selected:i,rangeStart:null,hoverTime:null}),this.emit("cal:time-change",{value:i}),this.display==="popover"&&this.close()}}_handleHover(e){this.mode==="range"&&this._store.set({hoverTime:e})}_updateSlotHighlight(e){const a=this.$$(".cal-time-slot"),{rangeStart:t,hoverTime:s,selected:i}=e,l=i&&typeof i=="object"&&i.start&&i.end;for(const c of a){const g=c.dataset.time;if(!(!g||c.disabled))if(t&&!l&&s){const h=u(t)<u(s)?t:s,m=u(t)<u(s)?s:t,d=u(g),n=d>u(h)&&d<u(m),o=g===t,p=g===s;c.classList.toggle("cal-time-slot--range-start",o),c.classList.toggle("cal-time-slot--range-end",p),c.classList.toggle("cal-time-slot--in-range",n)}else t||c.classList.remove("cal-time-slot--range-start","cal-time-slot--range-end","cal-time-slot--in-range")}}open(){this._popover&&(this._popover.open(),this._store.set({isOpen:!0}),this.emit("cal:open"))}close(){this._popover&&(this._popover.close(),this._store.set({isOpen:!1}),this.emit("cal:close"))}clear(){this._store.set({selected:null,rangeStart:null,hoverTime:null}),this.emit("cal:time-change",{value:null})}_renderTimepickerContent(){const e=this._store.getState(),a=document.createElement("div");a.classList.add("cal-timepicker"),e.statusType&&e.statusMessage&&a.appendChild(G({type:e.statusType,message:e.statusMessage,dismissible:e.statusDismissible,onDismiss:()=>this.clearStatus()}));const t=document.createElement("div");if(t.classList.add("cal-timepicker__header"),t.textContent="Select Time",a.appendChild(t),this.loading)a.appendChild(X({durationLabels:this.durationLabels}));else{const s=this._getEffectiveSlots(),i=H({slots:s,mode:this.mode,format:this.format,selected:e.selected,hoverTime:e.hoverTime,rangeStart:e.rangeStart,unavailableTimes:this._unavailableTimes,onSelect:l=>this._handleSelect(l),onHover:l=>this._handleHover(l),durationLabels:this.durationLabels});a.appendChild(i)}return a}_formatTriggerText(){const e=this._store.getState();return e.selected?this.mode==="single"&&typeof e.selected=="string"?e.selected:this.mode==="multi"&&Array.isArray(e.selected)&&e.selected.length?`${e.selected.length} time${e.selected.length>1?"s":""} selected`:this.mode==="range"&&typeof e.selected=="object"&&e.selected.start?`${e.selected.start} – ${e.selected.end}`:null:null}render(){var t;if(this._rendering)return;this._rendering=!0;const e=this.shadowRoot,a=[...e.childNodes];for(const s of a)s.nodeName!=="STYLE"&&!(s instanceof CSSStyleSheet)&&e.removeChild(s);if((t=this._popover)==null||t.destroy(),this._popover=null,this.display==="popover"){const s=document.createElement("div");s.classList.add("cal-popover-wrapper");const i=document.createElement("button");i.classList.add("cal-trigger");const l=document.createElement("span");l.classList.add("cal-trigger__icon"),l.innerHTML=Y,i.appendChild(l);const c=this._formatTriggerText(),g=document.createElement("span");c?g.textContent=c:(g.textContent=this.placeholder,g.classList.add("cal-trigger--placeholder")),i.appendChild(g),s.appendChild(i);const h=this._renderTimepickerContent(),m=R({trigger:i,content:h,onClose:()=>{this._store.set({isOpen:!1}),this.emit("cal:close")}});s.appendChild(m.panel),e.appendChild(s),i.addEventListener("click",d=>{d.stopPropagation(),m.isOpen?this.close():this.open()}),this._popover=m,this._store.get("isOpen")&&m.open()}else e.appendChild(this._renderTimepickerContent());this._rendering=!1}}customElements.get("cal-timepicker")||customElements.define("cal-timepicker",C),b.CalTimepicker=C,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})}));
517
517
  //# sourceMappingURL=timepicker.umd.js.map